大家好 我在 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$
最佳答案
仅在正则表达式无法匹配时才会出现的性能问题通常是由于 catastrophic backtracking 引起的.当正则表达式允许许多可能的组合来匹配主题文本时,就会发生这种情况,所有这些组合都必须由正则表达式引擎尝试,直到它可能宣布失败。
在您的情况下,失败的原因很明显:
首先,您所做的实际上不应该使用正则表达式来完成,而应该使用 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 个步骤。
关于c# - C# 中的 Regex.match 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5039512/