我正在编写一个词法解析器/分析器,它根据一组预定义的正则表达式分析指定的文本,我遇到了一些麻烦:
假设我们要分析包含N个部分的文本,例如
A, B, C[, N]
现在,我希望每个匹配的部分都可以在正则表达式中访问,因此我可以使用
访问以前匹配的部分$X
我的解决方案是使用(忽略任何隐含的空格或换行符)
([A-Za-z]*) //A
(?:\s|\n)* //Whitespace
((?:,) (?:\s|\n)* ([A-Za-z]* ))* //, B etc.
我想要的结果如下:
1. A
2. B
3. C
但我得到的结果是......不太理想:
1. A
2. , C
3. C
为什么会这样,以及如何改进它以正确匹配我的文字?
答案 0 :(得分:2)
问题是你正在重复你的捕获组,用下一个匹配结果覆盖每个匹配结果直到最后一个(所以在你的情况下, B
被, C
覆盖)。
这就是正则表达式的工作原理;像.NET这样的实现允许您访问重复组的所有单独捕获,但大多数不会。
更好地迭代你的比赛。如果你真的想保留分隔符(为什么?),你可以这样做:
(?:\s*,\s*)?[A-Za-z]+
在Python中:
>>> import re
>>> a = "A, B, C, D"
>>> r = re.compile(r"(?:\s*,\s*)?[A-Za-z]+")
>>> r.findall(a)
['A', ', B', ', C', ', D']
附注:\s
已包含\n
,因此(?:\s|\n)*
是多余的 - \s*
即可。
答案 1 :(得分:1)
这一行:
((?:,) (?:\s|\n)* ([A-Za-z]* ))* //, B etc.
这样做:
(?:(?:,) (?:\s|\n)* ([A-Za-z]* ))* //, B etc.
这是因为您的原始正则表达式“创建”了2个捕获:
()
(包括内部捕获组和非捕获组)([A-Za-z]* )
捕获组答案 2 :(得分:1)
让最大的群体无法捕捉:
(?:, (?:\s|\n)* ([A-Za-z]*))*
我还将(?:,)
简化为,
。
答案 3 :(得分:1)
只抓住[A-Za-z]+
群体为您服务吗?
public static void main(String[] foo) {
Pattern pattern = Pattern.compile("([a-zA-Z]+)(?:, )?");
Matcher matcher = pattern.matcher("A, B, C, D");
while (matcher.find()) {
System.out.println(matcher.group(1));
}
}
输出:
A
B
C
D
那够了吗?