正则表达式灾难性回溯仅在 .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();
}

然后我重新考虑使用枚举。逐行应用的咬大小正则表达式不再导致超时。

正则表达式灾难性回溯仅在 .net 中

以下内容似乎对我有用(为清楚起见,使用RegexOptions.IgnorePatternWhitespace):

@"(?<OuterDescription>[ 't]*--[ 't]+
    Description:[ 't]+
    (?!'<Description)
    (?<Description> 'S[^'r'n]{1,})
    (?<MultilineDescription>('r?'n|[^'r'n]*)*?)
    (?=[ 't]*--[ 't]*Modified)
)";

通常,嵌套贪婪量词会导致您遇到的问题。不幸的是,我太累了,无法深入研究它,但如果您对出了什么问题感到好奇,我可以做一个笔记,以便稍后调查