使用Java中的正则表达式拆分具有转义序列的字符串

要拆分的字符串

abc:def:ghi\:klm:nop 

应根据“:”分割字符串“\”是转义字符。 所以“\:”不应被视为令牌。

split(“:”)给出

 [abc] [def] [ghi\] [klm] [nop] 

必需的输出是字符串数组

 [abc] [def] [ghi\:klm] [nop] 

如何\:被忽略

使用后视断言 :

 split("(? 

只有在没有前面的\才会匹配。 使用双转义\\\\是必需的,因为字符串声明需要一个,正则表达式需要一个。

但请注意,在您希望允许令牌以反斜杠结尾的情况下,这将不允许您转义反斜杠。 要做到这一点,你必须先用所有双反斜杠替换

 string.replaceAll("\\\\\\\\", ESCAPE_BACKSLASH) 

(其中ESCAPE_BACKSLASH是一个不会出现在输入中的字符串),然后,在使用look-behind断言进行拆分后,将ESCAPE_BACKSLASH字符串替换为带有未转义的反斜杠

 token.replaceAll(ESCAPE_BACKSLASH, "\\\\") 

Gumbo使用后面的断言是正确的,但是如果你的字符串在逗号前面包含转义的转义字符(例如\\ ),则拆分可能会中断。 看这个例子:

test1\,test1,test2\\,test3\\\,test3\\\\,test4

如果你为(?做一个简单的后视分割(?就像Gumbo建议的那样,字符串被分成两部分,只有test1\,test1test2\\,test3\\\,test3\\\\,test4 。 这是因为后视只是检查一个字符返回转义字符。 如果字符串在逗号和逗号前面分隔偶数个转义字符,则实际上是正确的。

要实现这一目标,需要稍微复杂(双重)的后视表达式:

(?

在Java中使用这个更复杂的正则表达式,再次需要通过\\转义所有\ 。 所以这应该是对你的问题更复杂的答案:

 "any comma separated string".split("(? 

注意: Java不支持lookbehinds内部的无限重复。 因此,使用表达式{0,10}仅检查最多10个重复的双转义字符。 如果需要,您可以通过调整后一个数字来增加此值。