C# 如何处理来自用户提交的正则表达式的从不重复的匹配 让我们考虑下面C中的两条线(使用Framework .NET 3.5) Regex-Regex=newregex(@“^((E)E)t)?(M)oi(?[A-Za-z]\.\w*(\-\s)?[A-Za-z]?\w{1,})+$”,RegexOptions.Compiled | RegexOptions.IgnoreCase); Match m=正则表达式Match(“moi aussi jaimerai etre un ordinatur pour pasénnerver”);

C# 如何处理来自用户提交的正则表达式的从不重复的匹配 让我们考虑下面C中的两条线(使用Framework .NET 3.5) Regex-Regex=newregex(@“^((E)E)t)?(M)oi(?[A-Za-z]\.\w*(\-\s)?[A-Za-z]?\w{1,})+$”,RegexOptions.Compiled | RegexOptions.IgnoreCase); Match m=正则表达式Match(“moi aussi jaimerai etre un ordinatur pour pasénnerver”);,c#,.net,regex,user-input,C#,.net,Regex,User Input,(抱歉,这是一个法语节目:)) 当它们被执行时,进程会卡在Match()方法中,并且永远不会退出。我猜regex模式中的空白有一些问题,但我想做的不是更改模式(实际上它是在程序之外设置的,由我的工具的最终用户设置的),而是能够停止进程(例如超时) 有人知道这是否是.NET正则表达式的一个众所周知的问题,是否有一种简单的方法来解决它,或者我是否必须在需要时遍历这些行并中止它们(当然我不想这样做)。一般来说,正则表达式可能需要比您预期的更长的时间。您应该使用调节器之类的工具来试验正则表达式 问题是您

(抱歉,这是一个法语节目:))

当它们被执行时,进程会卡在
Match()
方法中,并且永远不会退出。我猜regex模式中的空白有一些问题,但我想做的不是更改模式(实际上它是在程序之外设置的,由我的工具的最终用户设置的),而是能够停止进程(例如超时)


有人知道这是否是.NET正则表达式的一个众所周知的问题,是否有一种简单的方法来解决它,或者我是否必须在需要时遍历这些行并中止它们(当然我不想这样做)。

一般来说,正则表达式可能需要比您预期的更长的时间。您应该使用调节器之类的工具来试验正则表达式

问题是您在正则表达式中嵌套了“循环”,这使得它效率极低(因此,由于表达式的复杂性,它基本上要花很长时间)


如果你说你想匹配什么,我可以试着找出一个更有效的正则表达式

比赛尝试提前中止 因为正则表达式太复杂了 复杂的。您计划使用的正则表达式引擎 使用时可能无法处理 这一切都会让你崩溃。查阅 未来的“灾难性回溯” 帮助文件以了解如何避免这种情况 情况

查找灾难性回溯给出了以下解释

失控的正则表达式:灾难性的回溯 考虑正则表达式(x+x+)+y。 在你惊恐地尖叫并说 这个人为的例子应该是 写为xx+y以完全匹配 同样没有那些可怕的嵌套 量词:假设每个“x” 代表更复杂的东西,, 某些字符串由 两者都是“x”。请参阅关于HTML的部分 下面是一个真实的例子

让我们看看你申请时会发生什么 将正则表达式转换为XXXXXXXXXX Y。第一 x+将匹配所有10个x字符。这个 第二个x+失败。第一个x+然后 回溯到9场比赛 第二个接剩下的x。 这组人现在已经配对过一次了。这个 组重复,但第一次失败 x+。因为有一次重复 足够了,组匹配。Y 匹配y,并且整体匹配为 建立正则表达式已声明 功能上,代码被发送到 客户,他的电脑爆炸了。 差不多

当y 主题字符串中缺少。 当y出现故障时,正则表达式引擎 回溯。这个团体有一个 它可以回溯到的迭代。这个 第二个x+只匹配一个x,所以 无法回溯。但是第一个x+可以 放弃一个x。第二个x+1 匹配xx。这个团体又有了一个 迭代,下一次失败,然后 y失败了。再次回溯,这个 第二个x+现在有一个回溯 位置,将自身缩小到与x匹配。 小组尝试第二次迭代。 第一个x+匹配,但第二个是 卡在绳子的末端。 再次回溯,中的第一个x+ 小组的第一次迭代减少了 将其自身设置为7个字符。第二个x+ 匹配xxx。如果是y,则是第二个x+ 减少到xx,然后是x。现在 组可以匹配第二次迭代, 每个x+对应一个x。但是这个 (7,1),(1,1)组合也失败了。所以 它转到(6,4),然后是(6,2)(1,1) 然后(6,1),(2,1)然后 (6,1),(1,2)然后我想你开始 明白大意

如果你在10倍的字符串上尝试这个正则表达式 在RegexBuddy的调试器中,需要 2558计算最终y的步骤 他失踪了。对于一个11倍的字符串,它 需要5118个步骤。对于12人来说,这需要时间 10238步。很明显,我们有一个 这里是O(2^n)的指数复杂性。 在21时,调试器在2.8时退出 百万步,诊断一个坏病例 灾难性的回溯

RegexBuddy很宽容,因为它 检测到它正在旋转,并且 中止匹配尝试其他正则表达式 引擎(如.NET)将继续运行 永远,而其他人将与你一起崩溃 堆栈溢出(如Perl,在 版本5.10)。堆栈溢出为 尤其是在窗户上,因为 他们倾向于提出你的申请 消失得无影无踪。 如果你运行一个网络,要非常小心 允许用户提供 它们自己的正则表达式。人 几乎没有正则表达式经验的人 出类拔萃的技巧 指数复正则 表情


我想你必须用代码来处理它。我建议您联系的作者,询问需要什么来检测这种情况。

我认为您只需在单独的线程上启动正则表达式匹配,并允许在达到某个最大时间限制时中止它。

在我看来,正则表达式匹配呈指数增长。看

最好的解决方案是在正则表达式上设置一个超时时间,而不要乱动线程


请参见此处的操作方法。

不,让用户输入自己的正则表达式是一个众所周知的问题:-/Pb.NET?那是VB.NET的法语版本吗?对不起,我还没学会这两种语言P@PierrOz:你的问题似乎有误导性。这与正则表达式无关。它是关于进程以及如果需要太长时间如何中止进程的。但是你将得到的所有答案将告诉你如何优化你的正则表达式。在我看来,这不是你要问的。我已经解决了这个问题
Regex regex = new Regex(@"^((E|e)t )?(M|m)oi (?<NewName>[A-Za-z]\.?\w*((\-|\s)?[A-Za-z]?\w{1,})+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
Match m = regex.Match("moi aussi jaimerai etre un ordinateur pour pas m'énnerver ");