字符串切割器:按逗号分割字符串并忽略双引号中的逗号。

7
我有一个以下格式的字符串 -

value1, value2, value3, value4, "value5, 1234", value6, value7, "value8", value9, "value10, 123.23"

如果我对上述字符串进行标记化,我会得到逗号分隔的标记。但我想告诉字符串标记器在拆分时忽略双引号后面的逗号。我该如何表示?
谢谢您提前的帮助。
沙西

11
使用CSV解析器吗?正则表达式可能会比较复杂。否则,请发布您已经尝试过的内容。 - Jerry
CSV解析器还可以让您统一处理带引号/不带引号的值。 - Ravi K Thapliyal
6个回答

6
使用类似OpenCSV的CSV解析器来处理带引号元素中的逗号、跨越多行的值等。您还可以使用该库将文本序列化为CSV格式。
String str = "value1, value2, value3, value4, \"value5, 1234\", " +
        "value6, value7, \"value8\", value9, \"value10, 123.23\"";

CSVReader reader = new CSVReader(new StringReader(str));

String [] tokens;
while ((tokens = reader.readNext()) != null) {
    System.out.println(tokens[0]); // value1
    System.out.println(tokens[4]); // value5, 1234
    System.out.println(tokens[9]); // value10, 123.23
}

3
您只需要一行正确的正则表达式:

```

您只需一行正确的正则表达式:```

String[] values = input.replaceAll("^\"", "").split("\"?(,|$)(?=(([^\"]*\"){2})*[^\"]*$) *\"?");

这也会为您整洁地削减掉双引号,包括最后一个引号!

注意:当第一个术语被引用时,有趣的边缘情况需要使用replaceAll()来削减前导引号。

以下是一些测试代码:

String input= "\"value1, value2\", value3, value4, \"value5, 1234\", " +
    "value6, value7, \"value8\", value9, \"value10, 123.23\"";
String[] values = input.replaceAll("^\"", "").split("\"?(,|$)(?=(([^\"]*\"){2})*[^\"]*$) *\"?");
for (String s : values)
System.out.println(s);

输出:

value1, value2
value3
value4
value5, 1234
value6
value7
value8
value9
value10, 123.23

2
我对正则表达式过敏;为什么不像某些人建议的那样使用双重分割呢?
    String str = "value1, value2, value3, value4, \"value5, 1234\", value6, value7, \"value8\", value9, \"value10, 123.23\"";
    boolean quoted = false;
    for(String q : str.split("\"")) {
        if(quoted)
            System.out.println(q.trim());
        else
            for(String s : q.split(","))
                if(!s.trim().isEmpty())
                    System.out.println(s.trim());
        quoted = !quoted;
    }

1

以下代码不依赖于任何第三方库,也可以根据要求解析字段:

import java.util.*;

public class CSVSpliter {

  public static void main (String [] args) {
    String inputStr = "value1, value2, value3, value4, \"value5, 1234\", value6, value7, \"value8\", value9, \"value10, 123.23\"";

    StringBuffer sb = new StringBuffer (inputStr);
    List<String> splitStringList = new ArrayList<String> ();
    boolean insideDoubleQuotes = false;
    StringBuffer field = new StringBuffer ();

    for (int i=0; i < sb.length(); i++) {
        if (sb.charAt (i) == '"' && !insideDoubleQuotes) {
            insideDoubleQuotes = true;
        } else if (sb.charAt(i) == '"' && insideDoubleQuotes) {
            insideDoubleQuotes = false;
            splitStringList.add (field.toString().trim());
            field.setLength(0);
        } else if (sb.charAt(i) == ',' && !insideDoubleQuotes) {
            // ignore the comma after double quotes.
            if (field.length() > 0) {
                splitStringList.add (field.toString().trim());
            }
            // clear the field for next word
            field.setLength(0);
        } else {
            field.append (sb.charAt(i));
        }
    }
    for (String str: splitStringList) {
        System.out.println ("Split fields: "+str);
    }
}

}

这将产生以下输出:

分割字段:value1

分割字段:value2

分割字段:value3

分割字段:value4

分割字段:value5, 1234

分割字段:value6

分割字段:value7

分割字段:value8

分割字段:value9

分割字段:value10, 123.23


1
你可以使用以下几种方法:
  1. 编写搜索逗号的代码,并维护特定逗号是否在引号内的状态。
  2. 通过双引号符号进行分词,然后通过逗号符号对结果数组中的字符串进行分词(确保对索引为0、2、4等的字符串进行分词,因为它们在原始字符串中没有被双引号括起来)。

0
String delimiter = ",";

String v = "value1, value2, value3, value4, \"value5, 1234\", value6, value7, \"value8\", value9, \"value10, 123.23\"";

String[] a = v.split(delimiter + "(?=(?:(?:[^\"]*+\"){2})*+[^\"]*+$)");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接