c# - C# 中的 Regex.match 性能问题

标签 c# regex

大家好 我在 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/

相关文章:

C# : size in properties is diffrent from code

C# WPF Slider 控件使刻度均匀显示

python - 如何在匹配正则表达式时捕获数字?

PHP 正则表达式从字符串 Markdown

正则表达式匹配双引号,但不匹配双引号对

c# - 使用 GetSaveFileName 创建 SaveFileDialog 时如何停止覆盖提示

c# - 使用 PostSharp Toolkit 构建在 4.5.1 上失败但适用于 4.5

c# - 如何在 C# 中使用动态键创建列表字典

javascript - 正则表达式替换文件名中的最后一个数字

regex - 在最后一次出现 '- ' 或 '|' 后截断字符串