如何才能使此正则表达式匹配正确?

时间:2011-10-26 12:20:11

标签: regex

我正在编写一个词法解析器/分析器,它根据一组预定义的正则表达式分析指定的文本,我遇到了一些麻烦:

假设我们要分析包含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

为什么会这样,以及如何改进它以正确匹配我的文字?

4 个答案:

答案 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

那够了吗?