如何在忽略转义逗号的同时拆分逗号分隔的String?

art*_*urh 26 java regex csv

我需要编写一个StringUtils.commaDelimitedListToStringArray函数的扩展版本,它获取一个额外的参数:escape char.

所以打电话给我:

commaDelimitedListToStringArray("test,test\\,test\\,test,test", "\\")
Run Code Online (Sandbox Code Playgroud)

应该返回:

["test", "test,test,test", "test"]
Run Code Online (Sandbox Code Playgroud)



我目前的尝试是使用String.split()使用正则表达式拆分String:

String[] array = str.split("[^\\\\],");
Run Code Online (Sandbox Code Playgroud)

但返回的数组是:

["tes", "test\,test\,tes", "test"]
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

mat*_*t b 32

正则表达式

[^\\],
Run Code Online (Sandbox Code Playgroud)

表示"匹配一个不是反斜杠后跟逗号的字符" - 这就是为什么模式t,匹配,因为这t是一个不是反斜杠的字符.

我认为你需要使用某种负面的lookbehind,以捕获,一个\没有捕获前面的字符而不是前面的字符,类似于

(?<!\\),
Run Code Online (Sandbox Code Playgroud)

(顺便说一句,请注意我故意没有双重逃脱反斜杠以使其更具可读性)

  • 这将再次错误地拆分一个字符串,例如“ test \\,tost”(也有意不进行两次转义),该字符串应已拆分为“ test \\”和“ tost”。为了克服这个问题,我曾经发现以下(Java)正则表达式:“(?&lt;=(?&lt;!\\\)(\\\\\){0,100}),”仍然不完美(并且仍然需要双重转义,即“(?&lt;=(?&lt;!\\\\\)(\\\\\\\\\\){0,100}),”)。但是会的 (2认同)

cle*_*tus 30

尝试:

String array[] = str.split("(?<!\\\\),");
Run Code Online (Sandbox Code Playgroud)

基本上这是用逗号分隔,除了逗号前面有两个反斜杠.这称为负后观零宽度断言.

  • 实际上,它匹配前面有一个反斜杠的逗号.在作为Java String文字编写的正则表达式中,它需要四个反斜杠以匹配目标文本中的ONE. (6认同)

art*_*urh 6

为了将来参考,这是我最终得到的完整方法:

public static String[] commaDelimitedListToStringArray(String str, String escapeChar) {
    // these characters need to be escaped in a regular expression
    String regularExpressionSpecialChars = "/.*+?|()[]{}\\";

    String escapedEscapeChar = escapeChar;

    // if the escape char for our comma separated list needs to be escaped 
    // for the regular expression, escape it using the \ char
    if(regularExpressionSpecialChars.indexOf(escapeChar) != -1) 
        escapedEscapeChar = "\\" + escapeChar;

    // see http://stackoverflow.com/questions/820172/how-to-split-a-comma-separated-string-while-ignoring-escaped-commas
    String[] temp = str.split("(?<!" + escapedEscapeChar + "),", -1);

    // remove the escapeChar for the end result
    String[] result = new String[temp.length];
    for(int i=0; i<temp.length; i++) {
        result[i] = temp[i].replaceAll(escapedEscapeChar + ",", ",");
    }

    return result;
}
Run Code Online (Sandbox Code Playgroud)