可选封闭csv字符串的Java正则表达式返回意外结果

可选封闭csv字符串的Java正则表达式返回意外结果,java,regex,Java,Regex,在Java中,我有一个字符串(取自csv文件): 我的类CSV\u Worker将按给定的分隔符(;)将其拆分,并在必要时删除引号: public class CSV_Worker { Pattern pattern = null; int colCount = -1; public CSV_Worker (String delimiter, int colCount) { // (?<=^|;)(?:"([^;]*)"|([^;]*))(?=;|$) th

在Java中,我有一个字符串(取自csv文件):

我的类
CSV\u Worker
将按给定的分隔符(
)将其拆分,并在必要时删除引号:

public class CSV_Worker {

  Pattern pattern = null;
  int colCount = -1;

  public CSV_Worker (String delimiter, int colCount) {
    // (?<=^|;)(?:"([^;]*)"|([^;]*))(?=;|$)
    this.pattern = Pattern.compile("(?<=^|\\" + delimiter + ")(?:\"([^\\" + delimiter + "]*)\"|([^\\" + delimiter + "]*))(?=\\" + delimiter + "|$)");
    this.colCount = colCount;
  }

  public String [] split (String line) {

    String [] result = new String[this.colCount];
    Matcher m = pattern.matcher(line);
    int idx = 0;
    while (m.find()) {
      result[idx] = m.group();
      idx++;
    }
    return result;
  }
}
而不是

40
blue-collar
married
...
?

编辑

多亏了@Fabian,解决方案变成了另一个regexp:

(?<=^|\|)"?((?<!")[^\|]*(?!")|(?<=")[^"]*(?="))"?(?=\||$)
(?使用
m.group()
可以获得整个匹配项(即组0),而不仅仅是其中一个捕获组的内容。这包括来自非捕获组的引号。此外,对于有引号的情况和没有引号的情况,您使用不同的捕获组。因此,您需要像这样使用
匹配器

String g1 = m.group(1);
result[idx] = (g1 == null ? m.group(2) : g1);

您还可以通过使用lookarounds只使用一个捕获组

Pattern pattern = Pattern.compile("(?<=^|\\" + delimiter + ")\"?((?<!\")[^\\" + delimiter + "]*(?!\")|(?<=\")[^\"]*(?=\"))\"?(?=\\" + delimiter + "|$)");

请改为使用拆分方法。

尝试
String[]result=line.replaceAll(“^\”\124;\“$”,“”)。拆分(“\”?;\”?”);
。基本上这是一个好主意,但引号不是相互独立的。字符串可能只包含带前导/尾随引号的元素,这必须保留在结果中。不要尝试使用正则表达式解析CSV数据。使用CSV解析器。这就是它们的用途。smart,谢谢你。我使用了第二种解决方案,因为它在s faster.btw:如果正面环视(或中的第二部分)被
(?)取代,您的解决方案将变得完美?
String g1 = m.group(1);
result[idx] = (g1 == null ? m.group(2) : g1);
Pattern pattern = Pattern.compile("(?<=^|\\" + delimiter + ")\"?((?<!\")[^\\" + delimiter + "]*(?!\")|(?<=\")[^\"]*(?=\"))\"?(?=\\" + delimiter + "|$)");
result[idx] = m.group(1);