正则表达式表现得很懒,应该是贪心的

时间:2010-03-07 02:23:41

标签: regex greedy non-greedy regex-greedy alternation

我认为默认情况下我的正则表达式会表现出我想要的贪婪行为,但它不在以下代码中:

 Regex keywords = new Regex(@"in|int|into|internal|interface");
 var targets = keywords.ToString().Split('|');
 foreach (string t in targets)
    {
    Match match = keywords.Match(t);
    Console.WriteLine("Matched {0,-9} with {1}", t, match.Value);
    }

输出:

Matched in        with in
Matched int       with in
Matched into      with in
Matched internal  with in
Matched interface with in

现在我意识到如果我只是按照长度降序对关键字进行排序,我可以让它为这个小例子工作,但是

  • 我想明白为什么会这样 没有按预期工作,
  • 我正在处理的实际项目 在正则表达式中有更多的单词 保持他们是很重要的 字母顺序。

所以我的问题是:为什么这是懒惰的,我该如何解决?

3 个答案:

答案 0 :(得分:12)

懒惰和贪婪仅适用于量词(?*+{min,max})。轮换总是按顺序匹配并尝试第一个可能的匹配。

答案 1 :(得分:6)

看起来你正在试图破解事情。要做到这一点,你需要整个表达式是正确的,你当前的表达式不是。试试这个......

new Regex(@"\b(in|int|into|internal|interface)\b");

“\ b”表示匹配字边界,并且是零宽度匹配。这是依赖于语言环境的行为,但通常这意味着空格和标点符号。作为零宽度匹配,它将不包含导致正则表达式引擎检测字边界的字符。

答案 2 :(得分:3)

根据RegularExpressions.info,正则表达式为eager。因此,当它通过piped expression时,它会在第一次完全匹配时停止。

我的建议是将所有关键字存储在数组或列表中,然后在需要时生成已排序的管道表达式。只要您的关键字列表没有更改,您只需要执行此操作。只需将生成的表达式存储在某种单独的单例中,然后在正则表达式执行时返回它。