使用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\,test1
和test2\\,test3\\\,test3\\\\,test4
。 这是因为后视只是检查一个字符返回转义字符。 如果字符串在逗号和逗号前面分隔偶数个转义字符,则实际上是正确的。
要实现这一目标,需要稍微复杂(双重)的后视表达式:
(?
在Java中使用这个更复杂的正则表达式,再次需要通过\\
转义所有\
。 所以这应该是对你的问题更复杂的答案:
"any comma separated string".split("(?
注意: Java不支持lookbehinds内部的无限重复。 因此,使用表达式{0,10}
仅检查最多10个重复的双转义字符。 如果需要,您可以通过调整后一个数字来增加此值。