C#性能问题中的Regex.match

C#性能问题中的Regex.match,c#,regex,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(?&

大家好 我在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$
^.*\t.*\t.*\t(?\d+)\t(?\w+)\t.*\t.*\t.*\t.*\t.*\t\s*(?[\d\,]+)\t.*\t.*\t(?\d{6})\t(?\d+)\t(?\t.[\d\.]{10}\t.\t.*\t.\t.\t.\t.*\t.\t.\t.\t.\t.\t.\t.\t.-\t+\t.*(?\d+)\t+\t.-\t.\t+\t.\t.\t$

预编译它通常有助于:

private static readonly Regex re = new Regex(pattern, RegexOptions.Compiled);
然而,我想知道在这个特定的案例中,它是否与regex绑定——可能是一些昂贵的反向引用。例如,Regex并不总是可以使用的工具


现在编辑,因为这似乎是分隔数据:


与正则表达式不同,分隔数据可以更有效地使用解析方法。您甚至可以通过
var parts=line.Split('\t')
(并通过索引访问
parts
),但如果失败,则可以选择控制分隔符等。

只有在正则表达式无法匹配时才会出现的性能问题通常是由于以下原因造成的。当正则表达式允许许多可能的组合来匹配主题文本时,就会发生这种情况,正则表达式引擎必须尝试所有这些组合,直到它可能声明失败为止

就您而言,失败的原因显而易见:

首先,您所做的不应该真正使用正则表达式,而应该使用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$
这是上面正则表达式的摘录

.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t\s*(?<netValue>[\d\.,]+)
它需要正则表达式引擎4602步骤来确定它不能匹配

如果你使用

(?:[^\t]*\t){9}\s*(?<netValue>[\d\.,]+)
(?:[^\t]*\t){9}\s*(?[\d\,]+)

相反,引擎需要30个步骤才能成功匹配,而失败尝试只需要39个步骤。

你能展示你的正则表达式吗?你能发布正则表达式让我们看看吗?问题很可能是由于正则表达式本身,所以我们需要看到它;几乎总是失败的比赛尝试扼杀了表现。向我们展示正则表达式,我相信我们可以帮助您对其进行微调。向我们展示应用正则表达式的代码和数据示例,我们将能够提供更多帮助。(我的意思是,编辑你的问题并将信息添加到其中;不要把它放在评论中。)(请参见我的编辑,现在你已经发布了格式)(细节-如果它由tab分隔,它不是真正的csv-它是;坦率地说,你的经理错了)谢谢Marc。我想你是对的。对于我的问题,正则表达式不是最好的解决方案。因为正则表达式似乎没有提供引用字段,所以在
\t
上拆分可能会起作用。你必须通过索引而不是名字来访问字段,但是正则表达式太模糊了,这可能会更准确。你帮了我很多。顺致敬意,感谢蒂姆,这是我的regexp。这是我的regexp。我的regexp。它是用来对一个CSCSCS文件(由\t分割)进行阶段化的一个CSCSV文件(由\t分割)的一个CSV文件(由\t分割)进行阶段化的一个CSCSV文件(由\t分割)的一个。。。。。。。。。。。。。。。。。。。。。......\\\\\t.\\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t.\t\t\t\t\t\t真的非常感谢,,蒂姆,我尝试了你的解决方案,程序加速得太快了。我想知道stackoverflow里的telent和amasing有多厉害!谢谢其他帮助我的人。也为我糟糕的英语感到抱歉。顺致敬意,光明会确认@TimPietzcker,你是怎么计算出步数的,尤其是4602步?您是否找到了简单的案例,并使用数学归纳法或其他方法为示例形式的示例字符串得出了公式,或者您是否有一个工具可以为您计算它?这样的工具会非常方便@Inigo:这就是RegexBuddy的调试器输出的内容:)()
1   2   3   4   5   6   7   8   9   X
(?:[^\t]*\t){9}\s*(?<netValue>[\d\.,]+)