4

我有一个在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 布尔值,它将确定我是否检查修改的行(与描述相同),然后以页眉/页脚结束。像这样

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();
}

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

4

1 回答 1

2

以下似乎对我有用(RegexOptions.IgnorePatternWhitespace为了清楚起见):

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

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

于 2013-10-11T22:15:43.987 回答