【发布时间】:2013-12-02 23:37:12
【问题描述】:
假设我有以下正则表达式; (我正在使用 java.util.regex 包。java 版本 1.7.0_21)
Pattern p = Pattern.compile("\\G[^,]*(,|$)");
反复调用 find(),我应该能够提取 CSV 中的字段,如下所示:
String myCSV = "a,b";
所以让我们用最简单的循环来试试吧。只需在每个匹配项上回显信息。
Matcher m = p.matcher(myCSV);
while (m.find()) {
System.out.println("Match found from: " + m.start()
+ " (included) to: " + m.end()+ " (excluded),"
+ " matching: '" + m.group() + "'. Does it hit end?" + m.hitEnd());
}
虽然我尝试构建我的正则表达式以使其不允许零长度匹配,但令人惊讶的是,它确实如此:
Match found from: 0 (included) to: 2 (excluded), matching: 'a,'. Does it hit end?false
Match found from: 2 (included) to: 3 (excluded), matching: 'b'. Does it hit end?true
Match found from: 3 (included) to: 3 (excluded), matching: ''. Does it hit end?true
看第三个匹配,在我的想法中不应该出现。事实上,我的正则表达式要求每个匹配都以 (,|$) 结尾。因此,第二次匹配需要到达并“消耗”字符串的末尾,才有效:它不会将其留给进一步的匹配!
并且这似乎在第二场比赛之后被 hitEnd 为真证实了!。
但是 这似乎没有被 find 内部状态考虑,它搜索进一步的匹配,并且此时它显然找到了它,因为正则表达式允许在字符串结尾时进行零长度匹配因为它是有效匹配,因为每个字段都允许为空字符串(如果不是这种情况,使用 + 而不是 * 显然可以解决问题)。
我在问两件事。
1) 解决此问题
2) 似乎两次匹配到字符串结尾的原因
【问题讨论】:
-
未经测试:尝试
"\\G((?=.)[^,])*,?"(再次提醒我,\\G是什么?)。 -
Per this part of Java tutorial,尝试“
+?”匹配Reluctant。