2

在我的 C# 项目中,我正在解析日期的文本。日期可以有多种格式,目的是找出并纠正一些日期格式错误。各种日期格式意味着一组定义的日期格式是不可行的。最初,我将一组大约 10 个正则表达式一个一个地应用于输入字符串。这在功能上很好,但是当字符串达到 200 KB 的文本时,性能就成了问题,因为该函数需要大约 150 毫秒。

我发现我可以通过将日期正则表达式仅应用于日期子字符串来显着提高性能。因此,如果所有日期都必须具有英文月份名称,则使用正则表达式

\b(January|February|March|April|May|June|July|August|September|October|November|December)\b

会找到他们。如果我然后做一些子字符串来匹配一个月左右的文本,整体功能性能大约是 25 毫秒,好多了。但是,子字符串/循环、长度检查代码不整洁,感觉不是一个很好的解决方案。我真正想要的是一个正则表达式来匹配月份和它周围的文本,比如

.{0,25}\b(January|February|March|April|May|June|July|August|September|October|November|December)\b.{0,25}

在功能上很好。然而,这个正则表达式的性能大约需要 3500 毫秒才能在相同的长输入字符串上找到匹配项。

现在类似的正则表达式

(?<=.{0,25})\b(January|February|March|April|May|June|July|August|September|October|November|December)\b.{0,25}

积极的后视在大约 15 毫秒内找到匹配项(由于非常减少的回溯,我接受并有所了解的原因)。但是,这对我的使用不起作用,因为我需要将月份名称前后的文本包含在匹配结果中。

所以,我的问题是,我可以有一个正则表达式,它具有使用后视的性能,但具有在匹配结果中提供所有文本的功能?

4

1 回答 1

2

性能增益是一种错觉。通常,类似的事情.{0,25}会导致很多回溯,这解释了您所看到的性能不佳。然而,当放置在一个look-behind中时,它会停止贪婪和回溯,look-behind将寻找最小的可能匹配,这意味着将尝试0个字符,没有回溯。这意味着后视完全没有用,因为它总是匹配月份名称之前的零个字符。

如果使用匹配的位置在月份名称上找到匹配后提取上下文怎么办?对于每个matchin ,在这些位置之前和之后regex.Matches(str)获取match.Index和和子字符串。match.Length

于 2013-01-05T10:20:17.937 回答