正则表达式灾难性回溯仅在 .net 中
本文关键字:net 灾难性 回溯 正则表达式 | 更新日期: 2023-09-27 18:35:06
我有一个在 http://gskinner.com/RegExr/上运行良好的正则表达式,http://regexhero.net/tester/它是.net。但是,它在我的 .net v4.5 代码中超时 (1h+)。
(?<OuterDescription>[ 't]*--[ 't]+Description:[ 't]+(?!'<Description)(?<Description>'S[^'r'n]{1,})(('r'n|'r|'n)(?![ 't]*--[ 't]*Modified)[^'r'n]*)*)
使用示例数据:
-- ========================================================================================================
-- Author: A Name
-- Create date: 11/26/2012
-- Description: A description
-- A multiline description
-------------------------------------- Group Name -----------------------------------------
-- More details
-- More details
--
-- Modified: 01/7/2012 - Some reason
-- Modified: 12/7/2012 - Some other reason
-- ========================================================================================================
我的代码看起来像这样
var isMatch = new Regex(pattern, RegexOptions.None, TimeSpan.FromMinutes(1)).IsMatch(_fileText);
希望外部描述从-- Description
捕获到-- Modified
之前
我已经把它缩小到接近结尾的[^'r'n]*
。我不知道如何解决这个问题以在 c# 中不超时
编辑:
感谢您的讨论和回答。它有助于将超时从描述中移出。不幸的是,我仍然遇到问题。这就是我到目前为止所拥有的
[ 't]*--[ 't]+={3,}
('r'n|'n|'r)
(?<OuterAuthor>[ 't]*--[ 't]+
Author:[ 't]+
(?!'<Author)
(?<Author>'S[^'r'n]+))
('r'n|'n|'r)
(?<OuterCreateDate>[ 't]*--[ 't]+
Create' [Dd]ate:[ 't]+
(?!'<Create)
(?<CreateDate>'S[^'r'n]{1,}))
('r'n|'n|'r)
(?<OuterDescription>[ 't]*--[ 't]+
Description:[ 't]+
(?!'<Description)
(?<Description>'S[^'r'n]+)
(?<MultilineDescription>(('r'n|'r|'n)|[^'r'n]*)*?)
(?=(
[ 't]*--[ 't]*Modified)|(
[ 't]*--[ 't]*={3,})
))
这工作正常,但是一旦我在此之后添加一些东西,它就会超时。
对不起,我没有先提到这个,我以为一个小小的贪婪的星星变化就是我所有的问题。为了了解最终图片,我有一个isAdd布尔值,它将确定我是否检查修改后的行(与描述相同),然后以页眉/页脚结尾。这样
var entireCommentHeaderNamedGroupsRegex = headerFooterRegex + newlineRegex
+ authorRegex + newlineRegex
+ createDateRegex + newlineRegex
+ descriptionRegex + newlineRegex
+ (_isAdded ? modifiedRegex + newlineRegex : "")
+ headerFooterRegex;
未修改时的更多示例数据:
-- =============================================
-- Author: Garrett Carson
-- Create date: 10/4/2013
-- Description: This is a test
-- =============================================
CREATE PROCEDURE dbo.ThisIsATest
AS
BEGIN
PRINT 'This is a test'
END
此外,正如评论中提到的,我对正则表达式(在这个规模上)相当陌生,所以如果这实际上不是灾难性的回溯,请原谅我的术语。
编辑 2
作为最后的编辑,我最终选择了穷人的 fsm。
string currentState = "LookForAuthor"
foreach (var line in lines) {
switch currentState {
case "LookForAuthor" : {
... use author regex ... save to author variable ...
if(found) currentState = "LookForCreateDate"
else throw new InvalidCommentException();
}
case "LookForCreateDate": {
... use createDate regex ... save to createDate variable ...
...
}
...
}
}
if (!_isAdded && !(currentState == "Modified-FirstLine" || currentState == "Modified-MoreLines")) {
throw new InvalidCommentException();
}
然后我重新考虑使用枚举。逐行应用的咬大小正则表达式不再导致超时。
以下内容似乎对我有用(为清楚起见,使用RegexOptions.IgnorePatternWhitespace
):
@"(?<OuterDescription>[ 't]*--[ 't]+
Description:[ 't]+
(?!'<Description)
(?<Description> 'S[^'r'n]{1,})
(?<MultilineDescription>('r?'n|[^'r'n]*)*?)
(?=[ 't]*--[ 't]*Modified)
)";
通常,嵌套贪婪量词会导致您遇到的问题。不幸的是,我太累了,无法深入研究它,但如果您对出了什么问题感到好奇,我可以做一个笔记,以便稍后调查