[英]Regex.match in C# performance problem
大家好我在C#中使用Regex.match來逐行逐步調整文本文件。 我發現當線條與模式不匹配時會花費更多時間(約2-4秒)。 但是比賽時花費的時間少於1秒。 誰能告訴我如何改善表現?
這是我正在使用的正則表達式:
^.*?\t.*?\t(?<npk>\d+)\t(?<bol>\w+)\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t\s*(?<netValue>[\d\.,]+)\t.*?\t.*?\t(?<item>\d{6})\t(?<salesDoc>\d+)\t(?<acGiDate>[\d\.]{10})\t.*?\t.*?\t.*?\t.*?\t.*?\t(?<delivery>\d+)\t\s*(?<billQuantity>\d+)\t.*?\t(?<material>[\w\-]+)\tIV$
僅在正則表達式無法匹配時出現的性能問題通常是由於災難性的回溯 。 當正則表達式允許許多可能的組合匹配主題文本時,會發生這種情況,所有這些都必須由正則表達式引擎嘗試,直到它可能聲明失敗。
在您的情況下,失敗的原因是顯而易見的:
首先,你正在做的事情不應該用正則表達式來完成,而應該使用CSV解析器(或者你的情況下是TSV解析器)。
但是,如果你堅持使用正則表達式,你仍然需要改變一些東西。 你的問題是分隔符\\t
也可以用點( .
)匹配,所以除非整個字符串匹配,否則正則表達式引擎必須嘗試排列,如上所述。
因此,向前邁出的一大步將是改變所有.*?
在適用的情況下進入[^\\t]*
,並使用{m,n}
運算符壓縮重復:
^(?:[^\t]*\t){2}(?<npk>\d+)\t(?<bol>\w+)(?:\t[^\t]*){9}\t\s*(?<netValue>[\d\.,]+)(?:\t[^\t]*){2}\t(?<item>\d{6})\t(?<salesDoc>\d+)\t(?<acGiDate>[\d\.]{10})(?:\t[^\t]*){5}\t(?<delivery>\d+)\t\s*(?<billQuantity>\d+)\t[^\t]*\t(?<material>[\w\-]+)\tIV$
我希望我沒有錯誤計算:)
僅用於說明:
匹配此文本
1 2 3 4 5 6 7 8 9 0
以上從你的正則表達式的摘錄
.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t\s*(?<netValue>[\d\.,]+)
采取正則表達式引擎39步。
但是,當您將此文本提供給它時:
1 2 3 4 5 6 7 8 9 X
它需要正則表達式引擎4602步驟來弄清楚它無法匹配。
如果你使用
(?:[^\t]*\t){9}\s*(?<netValue>[\d\.,]+)
相反,引擎需要30個步驟才能成功匹配,只有39個步驟才能嘗試失敗。
預編譯它通常有助於:
private static readonly Regex re = new Regex(pattern, RegexOptions.Compiled);
但是,我想知道在這個特定情況下它是否與正則表達式相關 - 可能是一些昂貴的反向引用。 正則表達式並不總是使用的工具,例如......
現在編輯,這似乎是分隔數據:
分隔數據可以更有效地使用解析方法,而不是正則表達式。 您甚至可能只使用var parts=line.Split('\\t')
(並按索引訪問parts
),但如果失敗 - 這個csv閱讀器可以選擇控制分隔符等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.