我有一个这样的字符串:

foo,bar,c;qual="baz,blurb",d;junk="quux,syzygy"

我想用逗号分隔,但我需要忽略引号中的逗号。我该怎么做呢?regexp方法似乎失败了;我想我可以手动扫描,并在看到报价时进入不同的模式,但如果使用已有的库就更好了。(编辑:我想我指的是已经是JDK的一部分或者已经是Apache Commons等常用库的一部分的库。)

上面的字符串应该分成:

foo
bar
c;qual="baz,blurb"
d;junk="quux,syzygy"

注意:这不是一个CSV文件,它是一个包含在一个更大的整体结构文件中的单个字符串


当前回答

试着看看(?!\"),(?!\")。这应该是相匹配的,那是不被包围的。

其他回答

您正处于一个恼人的边界区域,regexp几乎不起作用(正如Bart所指出的,转义引号会使生活变得困难),然而一个成熟的解析器似乎有点过头了。

如果您可能需要更大的复杂性,我会去寻找一个解析器库。比如这个

虽然我一般喜欢正则表达式,但对于这种依赖于状态的标记化,我相信一个简单的解析器(在这种情况下,它比这个词听起来要简单得多)可能是一个更干净的解决方案,特别是在可维护性方面,例如:

String input = "foo,bar,c;qual=\"baz,blurb\",d;junk=\"quux,syzygy\"";
List<String> result = new ArrayList<String>();
int start = 0;
boolean inQuotes = false;
for (int current = 0; current < input.length(); current++) {
    if (input.charAt(current) == '\"') inQuotes = !inQuotes; // toggle state
    else if (input.charAt(current) == ',' && !inQuotes) {
        result.add(input.substring(start, current));
        start = current + 1;
    }
}
result.add(input.substring(start));

如果你不关心保留引号内的逗号,你可以简化这种方法(不处理开始索引,没有最后一个字符的特殊情况),用其他东西替换引号中的逗号,然后以逗号分隔:

String input = "foo,bar,c;qual=\"baz,blurb\",d;junk=\"quux,syzygy\"";
StringBuilder builder = new StringBuilder(input);
boolean inQuotes = false;
for (int currentIndex = 0; currentIndex < builder.length(); currentIndex++) {
    char currentChar = builder.charAt(currentIndex);
    if (currentChar == '\"') inQuotes = !inQuotes; // toggle state
    if (currentChar == ',' && inQuotes) {
        builder.setCharAt(currentIndex, ';'); // or '♡', and replace later
    }
}
List<String> result = Arrays.asList(builder.toString().split(","));

http://sourceforge.net/projects/javacsv/

https://github.com/pupi1985/JavaCSV-Reloaded (前一个库的分支,它将允许生成的输出在不运行Windows时具有Windows行结束符\r\n)

http://opencsv.sourceforge.net/

适用于Java的CSV API

你能推荐一个用于读取(可能是写入)CSV文件的Java库吗?

Java库或应用程序转换CSV到XML文件?

我会这样做:

boolean foundQuote = false;

if(charAtIndex(currentStringIndex) == '"')
{
   foundQuote = true;
}

if(foundQuote == true)
{
   //do nothing
}

else 

{
  string[] split = currentString.split(',');  
}

与其使用超前和其他疯狂的正则表达式,不如先取出引号。也就是说,对于每个引号分组,将该分组替换为__IDENTIFIER_1或其他指示符,并将该分组映射为string,string的映射。

在使用逗号分隔之后,将所有映射的标识符替换为原始字符串值。