【发布时间】:2010-03-07 02:23:41
【问题描述】:
我认为默认情况下我的 Regex 会表现出我想要的贪婪行为,但它不在以下代码中:
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
现在我意识到,如果我只是按长度降序对关键字进行排序,我可以让它在这个小例子中工作,但是
- 我想了解为什么会这样 没有按预期工作,并且
- 我正在做的实际项目 在正则表达式中有更多的词和 把它们留在里面很重要 按字母顺序。
所以我的问题是:为什么这是懒惰的,我该如何解决?
【问题讨论】:
-
我不确定您的实际用法是否更复杂,但如果上面的示例实际上是您正在做的事情,我认为循环遍历查找的单词列表会好一千倍与 IndexOf 方法匹配。如果正则表达式只是交替包含一堆单词,性能可能会很糟糕。
-
@Josh - 不,示例已简化。实际的应用程序正在读取语言文件以生成词法分析器和语法分析器。我的正则表达式有点生疏;我的问题现在看起来很明显!
-
@Josh:正则表达式引擎可以针对这种情况进行很多优化,包括在未能匹配公共前缀后丢弃许多检查。例如,如果第一个字符不是“i”,则不会检查以“i”开头的任何分支。不确定 .NET 引擎是否会这样做,但如果没有,我会感到惊讶。
-
@Max,它确实构建了状态转换以加快匹配速度。如果 .Net 与其他长期建立和完善的正则表达式引擎相比,这是我所收集到的争论的问题。但它确实比 IndexOf 表现更好。 (我已经在工作中循环运行,以证明为什么同事应该使用正则表达式而不是 IndexOf... 根据匹配的内容,您可以获得数量级的速度提升。)
标签: regex greedy non-greedy regex-greedy alternation