正则表达式在Java中匹配未转义的逗号

时间:2014-03-20 11:47:27

标签: java regex

问题描述

我正在尝试使用String类提供的split()方法将a拆分为单独的字符串。文档告诉我它将分割参数的匹配,这是一个正则表达式。我使用的分隔符是逗号,但逗号也可以转义。我使用的转义字符是正斜杠/(只是为了通过不使用反斜杠来简化操作,因为这需要在Java和正则表达式中的字符串文字中进行额外的转义)。

例如,输入可能是:

a,b/,b//,c///,//,d///,

输出应为:

a
b,b/
c/,/
d/,

因此,字符串应该在每个逗号处拆分,除非该逗号前面有奇数个斜杠(1,3,5,7,...,∞),因为这意味着逗号被转义。

可能的解决方案

我最初的猜测是将它拆分为:

String[] strings = longString.split("(?<![^/](//)*/),");

但是这是不允许的,因为Java不允许无限的后视组。我可以通过将*替换为{0,2000}:

来将重现限制为2000
String[] strings = longString.split("(?<![^/](//){0,2000}/),");

但仍然会对输入施加约束。因此,我决定将这一反复出现在后视组中,并提出了这个问题:

String[] strings = longString.split("(?<!/)(?:(//)*),");

但是,它的输出是以下字符串列表:

a
b,b (the final slash is lacking in the output)
c/, (the final slash is lacking in the output)
d/,

为什么在第2和第3个字符串中省略了这些斜杠,我该如何解决它(用Java)?

4 个答案:

答案 0 :(得分:3)

您可以使用正面外观为逗号前面的偶数数字斜杠实现拆分:

String[] strings = longString.split("(?<=[^/](//){0,999999999}),");

但要显示所需的输出,您需要进一步删除剩余的转义:

String longString = "a,b/,b//,c///,//,d///,";
String[] strings = longString.split("(?<=[^/](//){0,999999999}),");
for (String s : strings)
    System.out.println(s.replaceAll("/(.)", "$1"));

输出:

a
b,b/
c/,/
d/,

答案 1 :(得分:2)

你非常接近。要克服lookbehind错误,您可以使用此解决方法:

String[] strings = longString.split("(?<![^/](//){0,99}/),")

答案 2 :(得分:1)

如果你不介意另一种使用正则表达式的方法,我建议使用.matcher

Pattern pattern = Pattern.compile("(?:[^,/]+|/.)+");
String test = "a,b/,b//,c///,//,d///,";
Matcher matcher = pattern.matcher(test);
while (matcher.find()) {
    System.out.println(matcher.group().replaceAll("/(.)", "$1"));
}

输出:

a
b,b/
c/,/
d/,

ideone demo

此方法将匹配除分隔逗号之外的所有内容(反向类型)。优点是它不依赖于外观。

答案 3 :(得分:0)

我喜欢正则表达式,但在这里手动编写代码并不容易,即

boolean escaped = false;
for(int i = 0, len = s.length() ; i < len ; i++){
    switch(s.charAt(i)){
    case "/": escaped = !escaped; break;            
    case ",": 
      if(!escaped){
         //found a segment, do something with it
      }
      //Fallthrough!
    default:
      escaped = false;
    }
}
// handle last segment