C# 仅在.net中使用正则表达式灾难性回溯

C# 仅在.net中使用正则表达式灾难性回溯,c#,.net,regex,C#,.net,Regex,我有一个在.net上运行良好的正则表达式。然而,在我的.NETV4.5代码中它超时(1h+) (?<OuterDescription>[ \t]*--[ \t]+Description:[ \t]+(?!\<Description)(?<Description>\S[^\r\n]{1,})((\r\n|\r|\n)(?![ \t]*--[ \t]*Modified)[^\r\n]*)*) 我的代码如下所示 var isMatch = new Regex(patte

我有一个在.net上运行良好的正则表达式。然而,在我的.NETV4.5代码中它超时(1h+)

(?<OuterDescription>[ \t]*--[ \t]+Description:[ \t]+(?!\<Description)(?<Description>\S[^\r\n]{1,})((\r\n|\r|\n)(?![ \t]*--[ \t]*Modified)[^\r\n]*)*)
我的代码如下所示

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,})
    ))
未修改时的更多示例数据:

-- =============================================
-- 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
):

(?[\t]*-[\t]+ 说明:[\t]+
(?!\据我所知,正则表达式从不回溯…你确定超时是由于正则表达式造成的吗?也许你只是在分析一个巨大的文件?@CommuSoft你错了。总之,Garret,你希望得到什么输出,也许我可以用一个更好的正则表达式来代替你的问题?你需要指定正则表达式选项。多行I试想,既然您使用“^”作为行的开头。Garrett,我怀疑您发布的示例文本片段是否会导致灾难性的回溯。如果我们没有实际导致问题的输入数据,我们应该如何调试您的正则表达式?:)@嗅探器:根据我对编译器的工作,我知道正则表达式被编译成一个非确定性有限自动机,然后这种自动机被修改成确定性自动机(使用动态编程)决定O(n)中的输入。不能在线性时间内运行的所有内容都不应称为正则表达式,并且可以执行有限状态机以外的操作…谢谢。这有助于将超时移出描述区域。但是,我仍然无法在没有超时的情况下在此正则表达式之后添加任何内容。请参阅question@GarrettCarson,很抱歉,但是看你的编辑,它单个正则表达式解决方案看起来太复杂了,不适合使用。我建议您只使用自己的状态机解析器——它可以在内部使用正则表达式,但比将所有内容都放到单个大型正则表达式中更易于维护和调试。
-- =============================================
-- 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
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();
}
@"(?<OuterDescription>[ \t]*--[ \t]+
    Description:[ \t]+
    (?!\<Description)
    (?<Description> \S[^\r\n]{1,})
    (?<MultilineDescription>(\r?\n|[^\r\n]*)*?)
    (?=[ \t]*--[ \t]*Modified)
)";