我正在(用 C#)编写一个简单的解析器来处理看起来很像经典 C 的脚本语言。
在我拥有的一个脚本文件中,我用来识别 /* 块注释 */ 的正则表达式会进入某种无限循环,长时间占用 100% 的 CPU。
我使用的正则表达式是这样的:
/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/
关于为什么这可能被锁定有什么建议吗?
或者,我可以使用另一个正则表达式吗?
更多信息:
- 使用面向 .NET 3.5 的 C# 3.0 工作;
- 我使用 Regex.Match(string,int) 方法在字符串的特定索引处开始匹配;
- 我已经让程序运行了一个多小时,但比赛尚未完成;
- 传递给正则表达式构造函数的选项是
RegexOptions.Multiline
and RegexOptions.IgnorePatternWhitespace
;
- 正则表达式适用于我的 453 个测试文件中的 452 个。
我发现你的正则表达式存在一些问题:
没有必要|[\r\n]
正则表达式中的序列;否定的字符类,例如[^*]
匹配所有内容,除了*
,包括行分隔符。这只是.
(点)与这些不匹配的元字符。
进入评论后,您唯一需要查找的字符就是星号;只要你没有看到其中一个,你就可以吞下任意数量的角色。这意味着使用没有意义[^*]
当你可以使用[^*]+
反而。事实上,你不妨把它放在一个原子组中——(?>[^*]+)
——因为一旦你匹配了那些非星号,你就没有任何理由放弃它们。
过滤掉无关的垃圾,最外面的括号内的最终选择是\*+[^*/]
,这意味着“一个或多个星号,后跟一个不是星号或斜线的字符”。这将始终与注释末尾的星号匹配,并且总是必须再次放弃它,因为下一个字符是斜杠。事实上,如果最后一个斜杠前有二十个星号,则正则表达式的该部分将与所有星号匹配,然后它将一一放弃所有星号。然后是最后一部分——\*+/
-- 将永远匹配它们。
为了获得最大性能,我会使用这个正则表达式:
/\*(?>(?:(?>[^*]+)|\*(?!/))*)\*/
这将很快匹配一个格式良好的注释,但更重要的是,如果它开始匹配某些内容isn't一个有效的评论,它会尽快失败。
致谢David https://stackoverflow.com/questions/462843/improving-fixing-a-regex-for-c-style-block-comments/463339?noredirect=1#comment55996077_463339,这是一个将嵌套注释与任何嵌套级别相匹配的版本:
(?s)/\*(?>/\*(?<LEVEL>)|\*/(?<-LEVEL>)|(?!/\*|\*/).)+(?(LEVEL)(?!))\*/
它使用.NET 的平衡组,因此它不适用于任何其他风格。为了完整起见,这里有另一个版本(来自 RegexBuddy 的库),它使用 Perl、PCRE 和 Oniguruma/Onigmo 支持的递归组语法:
/\*(?>[^*/]+|\*[^/]|/[^*])*(?>(?R)(?>[^*/]+|\*[^/]|/[^*])*)*\*/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)