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

标签 java regex

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

40;"blue-collar";"married";"secondary";"no";1100;"yes";"no";"unknown";29;"may";660

我的类CSV_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;
  }
}

为什么CSV_Worker.split(myString)返回

40
"blue-collar"
"married"
...

而不是

40
blue-collar
married
...

编辑

感谢@Fabian,解决方案是另一个正则表达式:

(?<=^|\|)"?((?<!")[^\|]*(?!")|(?<=")[^"]*(?="))"?(?=\||$)

enter image description here

Debuggex Demo

最佳答案

使用m.group(),您可以获得整个匹配项(即组 0),而不仅仅是捕获组之一的内容。这包括非捕获组的引用。此外,对于有引号的情况和没有引号的情况,您可以使用不同的捕获组。因此,您需要像这样使用 Matcher:

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);

改为 split 方法。

关于用于可选封闭的 csv 字符串的 Java 正则表达式返回意外结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39673496/

相关文章:

java - 在数据库中存储带换行符的TextArea数据并以带换行符的相同格式显示

java - 使用 Java 以编程方式确定 2 个图像看起来是否相同

java - 如何避免在使用 pdfHtml 生成的 PDF 中添加不需要的空白?

regex - 编辑电话号码

java - 简单的java正则表达式匹配和替换

.net - .NET 的 RegEx 中的组和匹配有什么区别?

java - 用一个变量设置两个 Object.date 属性给我带来了问题

java - Wildfly10 到 Wildfly13 hibernate ogm 部署错误

python - 使用 REGEX 提取模式之间的文本

vb.net - 使用正则表达式替换将 10000 添加到数字?