c# - 仅在 .net 中的正则表达式灾难性回溯

标签 c# .net regex

我有一个在 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);

希望 OuterDescription 从 -- 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,})
    ))

这很好用,但是一旦我在此之后添加一些东西,它就会超时。

抱歉,我没有先提到这个,我以为一个小小的贪婪的星际变化将是我所有的问题。为了了解最终图片,我有一个 isAdded bool 值,它将确定我是否检查修改过的行(与描述相同)然后以页眉/页脚结束。像这样

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)
)";

一般来说,嵌套贪婪量词会导致您遇到的问题。不幸的是,我太累了,无法深入调查,但如果你对出了什么问题感到好奇,我可以记下来稍后再调查

关于c# - 仅在 .net 中的正则表达式灾难性回溯,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19327911/

相关文章:

c# - 如何将从外部登录提供程序获取的有关用户的数据获取到他的 ClaimsIdentity 中?

c# - Windows Phone 8.1 加速计检测到震动

.net - iOS <-> PC USB 通讯

.net - 不能将 try/与序列表达式内的 block 一起使用。如何绕过它?

c# - 搜索并添加到按字母顺序排列的列表

c# - 我可以动态地将 TextBlock.Text 的一部分设置为不同的颜色吗?

.net - 带有 WCF 的 JSON-P 示例?

asp.net - 如何在正则表达式中允许双引号?

python - 此正则表达式对于 xsd :anyURI 是否正确

Javascript 密码不应包含用户的帐户名或用户全名中超过两个连续字符的部分