大家好我在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$
Run Code Online (Sandbox Code Playgroud)
仅在正则表达式无法匹配时出现的性能问题通常是由于灾难性的回溯.当正则表达式允许许多可能的组合匹配主题文本时,会发生这种情况,所有这些都必须由正则表达式引擎尝试,直到它可能声明失败.
在您的情况下,失败的原因是显而易见的:
首先,你正在做的事情不应该用正则表达式来完成,而应该使用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$
Run Code Online (Sandbox Code Playgroud)
我希望我没有错误计算:)
仅用于说明:
匹配此文本
1 2 3 4 5 6 7 8 9 0
Run Code Online (Sandbox Code Playgroud)
以上从你的正则表达式的摘录
.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t.*?\t\s*(?<netValue>[\d\.,]+)
Run Code Online (Sandbox Code Playgroud)
采取正则表达式引擎39步.
但是,当您将此文本提供给它时:
1 2 3 4 5 6 7 8 9 X
Run Code Online (Sandbox Code Playgroud)
它需要正则表达式引擎4602步骤来弄清楚它无法匹配.
如果你使用
(?:[^\t]*\t){9}\s*(?<netValue>[\d\.,]+)
Run Code Online (Sandbox Code Playgroud)
相反,引擎需要30个步骤才能成功匹配,只有39个步骤才能尝试失败.