正则表达式和逃脱和未转义的分隔符

与此相关的问题

我有一个字符串

a\;b\\;c;d 

在Java中看起来像

 String s = "a\\;b\\\\;c;d" 

我需要用分号按照以下规则拆分它:

  1. 如果分号前面有反斜杠,则不应将其视为分隔符(在ab之间)。

  2. 如果反斜杠本身被转义,因此不会以分号方式转义,那么分号应该是分隔符(在bc之间)。

因此,如果在它之前存在零或偶数个反斜杠,则应将分号视为分隔符。

例如上面,我想得到以下字符串(java编译器的双反斜杠):

 a\;b\\ c d 

你可以使用正则表达式

 (?:\\.|[^;\\]++)* 

匹配未转义分号之间的所有文本:

 List matchList = new ArrayList(); try { Pattern regex = Pattern.compile("(?:\\\\.|[^;\\\\]++)*"); Matcher regexMatcher = regex.matcher(subjectString); while (regexMatcher.find()) { matchList.add(regexMatcher.group()); } 

说明:

 (?: # Match either... \\. # any escaped character | # or... [^;\\]++ # any character(s) except semicolon or backslash; possessive match )* # Repeat any number of times. 

由于嵌套量词,占有性匹配( ++ )对于避免灾难性回溯非常重要。

 String[] splitArray = subjectString.split("(? 

这应该工作。

说明:

 // (? 

所以你只需匹配前面没有前面的分号。

编辑:

 String[] splitArray = subjectString.split("(? 

这将照顾任何奇数。 如果你的数量超过4000000,它当然会失败。 编辑答案的说明:

 // (? 

我不相信用任何正则表达式来检测这些案例。 我通常会为这样的事情做一个简单的循环,我会用C描绘它,因为它很久以前我最后一次触及Java 😉

 int i, len, state; char c; for (len=myString.size(), state=0, i=0; i < len; i++) { c=myString[i]; if (state == 0) { if (c == '\\') { state++; } else if (c == ';') { printf("; at offset %d", i); } } else { state--; } } 

优点是:

  1. 您可以在每个步骤上执行语义操作。
  2. 把它移植到另一种语言很容易。
  3. 您不需要为这个简单的任务包含完整的正则表达式库,这增加了可移植性。
  4. 它应该比正则表达式匹配器快很多。

此方法假定您的字符串在字符串中不具有char '\0' 。 如果你这样做,你可以使用其他一些char。

 public static String[] split(String s) { String[] result = s.replaceAll("([^\\\\])\\\\;", "$1\0").split(";"); for (int i = 0; i < result.length; i++) { result[i] = result[i].replaceAll("\0", "\\\\;"); } return result; } 

这是我认为的真正答案。 在我的情况下,我试图分裂使用| 和转义字符是&

  final String regx = "(?

|e|”.split(regx); System.out.println(Arrays.toString(res));

在这段代码中,我使用Lookbehind来逃避和角色。 请注意,背后的外观必须具有最大长度。

 (? 

这意味着任何| 除了那些((?:[^&]|^)(&&){0,10000}&)) ,这部分意味着任何奇数的& s。 部分(?:[^&]|^)对于确保计算|后面的所有& s非常重要 到开头或其他一些角色。