大家好,我在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$发布于 2011-02-18 17:25:57
只有当正则表达式不匹配时才会出现性能问题,这通常是由于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使用上面的regex中的摘录
.*?\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个步骤。
发布于 2011-02-18 17:21:51
预编译通常会有帮助:
private static readonly Regex re = new Regex(pattern, RegexOptions.Compiled);然而,我想知道在这个特定的情况下,它是否与regex绑定-也许是一些昂贵的反向引用。正则表达式并不总是可以使用的工具,例如...
现在编辑,因为这似乎是分隔数据:
与正则表达式相比,带分隔符的数据可以更有效地使用解析方法。您甚至可能只使用var parts=line.Split('\t') (并通过索引访问parts ),但如果失败了-此csv reader有选项来控制分隔符等。
https://stackoverflow.com/questions/5039512
复制相似问题