Java String.split()正则表达式,用于处理转义分隔符和转义转义字符

时间:2014-03-20 18:04:53

标签: java regex string

String testString = "a\\,b\\\\,c,d\\\\\\,e,f\\\\g";
String[] splitedString = test.split(PATTERN_STRING);
for (String string : splitedString) {
    System.out.println(string);
}

这里我有一个字符串,它将String字符串编码为String,其中转义字符为\且分隔符为,注意:(由于Java代码,示例中的反斜杠加倍)
反斜杠和逗号被转义在原始字符串中,结果字符串与逗号合并。我需要一个正则表达式将此字符串拆分为原始的字符串列表 因此,对于字符串

"a\,b\\,c,d\\\,e,f\\g"
的示例,我需要获得这样的字符串:

"a\,b\\"
"c"
"d\\\,e"
"f\\g"

所以split的逻辑很简单:只有当前面的反斜杠数是偶数时才用分隔符逗号分隔:0,2,4 ......只有在这种情况下这个逗号是分隔符。如果逗号之前的反斜杠数是奇数,则转义为逗号,不应发生拆分。

对于这种情况,有人可以帮我使用适当的正则表达式吗?

编辑
我知道这个正则表达式:(?<!\\\\),将有助于使用之前没有反斜杠的逗号分隔字符串。但在我的情况下,我需要拆分以防止逗号数为斜线之前的斜线。

感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

如果必须拆分,那么你可以试试像

这样的东西
split("(?<!(?<!\\\\)\\\\(\\\\{2}){0,1000000000}),")

我使用了{0,1000000000}而不是*,因为Java中的后视需要有明显的最大长度,而1000000000似乎已经足够好了,除非你有超过{{{ 1}}文字中的连续1000000000


如果它不是\\,那么您可以使用

split

Matcher m = Pattern.compile("(\\G.*?(?<!\\\\)(\\\\{2})*)(,|(?<!\\G)$)", Pattern.DOTALL).matcher(testString); while (m.find()) { System.out.println(m.group(1)); } 表示上一次匹配结束,或者如果这是Matcher的第一次迭代,并且字符串\\G之前没有匹配开始。


但是实现速度最快且不那么热衷的是编写自己的解析器,它将使用^之类的标志来表示当前检查的字符是使用escaped转义的。

\

所有方法的演示:

public static List<String> parse(String text) {
    List<String> tokens = new ArrayList<>();
    boolean escaped = false;
    StringBuilder sb = new StringBuilder();

    for (char ch : text.toCharArray()) {
        if (ch == ',' && !escaped) {
            tokens.add(sb.toString());
            sb.delete(0, sb.length());
        } else {
            if (ch == '\\')
                escaped = !escaped;
            else
                escaped = false;
            sb.append(ch);
        }
    }

    if (sb.length() > 0) {
        tokens.add(sb.toString());
        sb.delete(0, sb.length());
    }

    return tokens;
}

输出:

String testString = "a\\,b\\\\,c,d\\\\\\,e,f\\\\g";
String[] splitedString = testString
        .split("(?<!(?<!\\\\)\\\\(\\\\{2}){0,1000000000}),");
for (String string : splitedString) {
    System.out.println(string);
}

System.out.println("-----");
Matcher m = Pattern.compile("(\\G.*?(?<!\\\\)(\\\\{2})*)(,|(?<!\\G)$)",
        Pattern.DOTALL).matcher(testString);
while (m.find()) {
    System.out.println(m.group(1));
}

System.out.println("-----");
for (String s : parse(testString))
    System.out.println(s);

答案 1 :(得分:0)

尝试,

我只是通过使用字符串操作来实现你的逻辑。

String string = "a\\,b\\\\,c,d\\\\\\,e,f\\\\g";
String finalString = "";
for(String i : string.split(",")){
    int count = 0;
    for(int j=0;j<i.length();j++)
        if(i.charAt(j) == '\\')
            count++;    
    finalString+=(count%2==0)?","+i+"$":","+i;
} 
for(String finalAns: finalString.split("\\$")){
    System.out.println(finalAns.replaceFirst(",", ""));
}

输出:

a\,b\\
c
d\\\,e
f\\g

答案 2 :(得分:0)

这将为您解决问题:

String[] splitedString = testString.split("(?<=[a-z])(\\\\{2})*,");

这里,它使用字符串中的\的偶数(0是偶数),然后是,用于分割分隔符。

使用lookbehind,检查\之前的最后一个字符是否为字母。