[英]Regex IsMatch taking too long to execute
我在使用RegEx的.NET項目中遇到一個奇怪的問題。 請參閱下面的C#代碼:
const string PATTERN = @"^[a-zA-Z]([-\s\.a-zA-Z]*('(?!'))?[-\s\.a-zA-Z]*)*$";
const string VALUE = "Ingebrigtsen Myre (Øvre)";
System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(PATTERN);
if (!regex.IsMatch(VALUE)) // <--- Infinite loop here
return string.Empty;
// Some other code
我使用此模式來驗證所有類型的名稱(拳頭名稱,姓氏,中間名等)。 值是一個參數,但我在上面作為常量提供了它,因為問題很少經常出現-僅帶有特殊符號:*,(,)等(對不起,但我沒有這些符號的完整列表) 。
您能幫我解決這個無限循環嗎? 謝謝你的幫助。
補充:這段代碼位於項目的最基本級別,我不想在那里進行任何重構-我只想快速解決此問題。
補充2:我確實知道從技術上講這不是循環-我的意思是“ regex.IsMatch(VALUE)”永無止境。 我等待了大約一個小時,它仍在執行。
非平凡的正則表達式: ^[a-zA-Z]([-\\s\\.a-zA-Z]*('(?!'))?[-\\s\\.a-zA-Z]*)*$
最好在自由空間模式下用注釋編寫,如下所示:
Regex re_orig = new Regex(@"
^ # Anchor to start of string.
[a-zA-Z] # First char must be letter.
( # $1: Zero or more additional parts.
[-\s\.a-zA-Z]* # Zero or more valid name chars.
( # $2: optional quote.
' # Allow quote but only
(?!') # if not followed by quote.
)? # End $2: optional quote.
[-\s\.a-zA-Z]* # Zero or more valid name chars.
)* # End $1: Zero or more additional parts.
$ # Anchor to end of string.
",RegexOptions.IgnorePatternWhitespace);
用英語來說,此正則表達式本質上說: “匹配一個以字母[a-zA-Z]
開頭,然后是零個或多個字母,空格,句點,連字符或單引號的字符串,但是每個單引號可能不會立即然后再加上一個單引號。”
請注意,您上面的正則表達式允許使用"ABC---...'... -.-.XYZ "
名稱,例如: "ABC---...'... -.-.XYZ "
,可能不是您所需要的名稱。 它還允許多行輸入和以空格結尾的字符串。
上面的正則表達式的“無限循環”問題是,當將此正則表達式應用於行中包含兩個單引號的長無效輸入時,會發生災難性的回溯 。 這是一個等效模式,它匹配(但不匹配)完全相同的字符串,但不會發生災難性的回溯:
Regex re_fixed = new Regex(@"
^ # Anchor to start of string.
[a-zA-Z] # First char must be letter.
[-\s.a-zA-Z]* # Zero or more valid name chars.
(?: # Zero or more isolated single quotes.
' # Allow single quote but only
(?!') # if not followed by single quote.
[-\s.a-zA-Z]* # Zero or more valid name chars.
)* # Zero or more isolated single quotes.
$ # Anchor to end of string.
",RegexOptions.IgnorePatternWhitespace);
在您的代碼上下文中,它是簡寫形式:
const string PATTERN = @"^[a-zA-Z][-\s.a-zA-Z]*(?:'(?!')[-\s.a-zA-Z]*)*$";
查看正則表達式的這一部分:
( [-\s\.a-zA-Z]* ('(?!'))? [-\s\.a-zA-Z]* )*$
^ ^ ^ ^ ^
| | | | |
| | | | This group repeats any number of times
| | | charclass repeats any number of times
| | This group is optional
| This character class also repeats any number of times
Outer group (repeated, as seen above)
這意味着只要您輸入的字符串包含不在字符類中的字符(例如示例中的方括號和非ASCII字母),前面的字符就會在許多排列中進行嘗試,排列的數目會隨着長度的增加而呈指數增加的字符串。
為了避免這種情況(並允許正則表達式更快失敗,請使用原子組 :
const string PATTERN = @"^[a-zA-Z](?>(?>[-\s\.a-zA-Z]*)(?>'(?!'))?(?>[-\s\.a-zA-Z])*)*$";
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.