在 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,解决方案是另一个正则表达式:
(?<=^|\|)"?((?<!")[^\|]*(?!")|(?<=")[^"]*(?="))"?(?=\||$)
最佳答案
使用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/