我有一个在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();
}
然后我重新考虑使用枚举。逐行应用的一口大小的正则表达式不再导致超时。