在 java 中使用正则表达式解析 CSV 输入

2022-09-03 01:54:47

我知道,现在我有两个问题。但是我玩得很开心!

我从这个建议开始,不是试图分裂,而是匹配一个可接受的领域,并从那里扩展到这个表达。

final Pattern pattern = Pattern.compile("\"([^\"]*)\"|(?<=,|^)([^,]*)(?=,|$)");

表达式看起来像这样,没有烦人的转义引号:

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

这对我来说很有效 - 要么它匹配“两个引号和它们之间的任何东西”,要么“行首或逗号与行尾或逗号之间的某些东西”。循环访问匹配项可以获得所有字段,即使它们是空的。例如

the quick, "brown, fox jumps", over, "the",,"lazy dog"

分解为

the quick
"brown, fox jumps"
over
"the"

"lazy dog"

伟大!现在我想删除引号,所以我添加了前瞻和查找非捕获组,就像我对逗号所做的那样。

final Pattern pattern = Pattern.compile("(?<=\")([^\"]*)(?=\")|(?<=,|^)([^,]*)(?=,|$)");

表达式再次为:

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

而不是期望的结果

the quick
brown, fox jumps
over
the

lazy dog

现在我得到这个细分:

the quick
"brown
 fox jumps"
,over,
"the"
,,
"lazy dog"

我错过了什么?


答案 1

运算符优先级。基本上没有。一切都是从左到右。因此,or(|)适用于结束引号前瞻和逗号前瞻

尝试:

(?:(?<=")([^"]*)(?="))|(?<=,|^)([^,]*)(?=,|$)

答案 2
(?:^|,)\s*(?:(?:(?=")"([^"].*?)")|(?:(?!")(.*?)))(?=,|$)

这应该做你想做的事。

解释:

(?:^|,)\s*

该模式应以 或字符串开头开始。此外,请忽略开头的所有空格。

看看其余的是否以报价开头

(?:(?=")"([^"].*?)")

如果是这样,则不贪婪地匹配直到下一个报价。

(?:(?!")(.*?))

如果它不以引号开头,则不贪婪地匹配,直到下一个逗号或字符串末尾。

(?=,|$)

该模式应以逗号或字符串结尾结尾。