2016-04-13 19 views
0

我有一个简单的正则表达式(在C#中使用):如何不让正则表达式做出太多步骤?

\becua(?:[a-zA-ZáéíóúñÑÑäëïöü])*\b(.(?!embajada))*\s+embajada 

1)字开头 “ecua”
2)无论之后附带该
3)单词 “Embajada酒店” 之后“无论“

但它使太多的步骤,我该如何防止这种情况?我只是希望它能够通过字符,直到找到“embajada”这个单词,而不是在每一个字符上都回溯。这似乎是简单的正则表达式,但是当我用一个更大的文本,它抛出一个灾难性的回溯(或超时)当模式失败

例子:https://regex101.com/r/tQ7mM9/4

在此先感谢

+0

你必须使用'(?= Embajada酒店)'代替'(?!Embajada酒店) ',我想 – rock321987

+0

你的文字中没有“embajada”这个词,只有“gembajada”。 –

+0

我会展开它:https://regex101.com/r/iR5eW3/1 –

回答

1

你可以写你的模式在一个贪婪的方式,但这次封闭所有量词在原子组中的部分。要做到这一点,你显然需要进行试验以前瞻,但限制太多测试的影响,则可以使用字符类[^e]这里)帮助正则表达式引擎仅在有趣的位置进行测试:

\becua(?>\w*[^e]*(?:\Be[^e]*|e(?!mbajada\b)[^e]*)*)embajada 

细节:

\becua 
(?> 
    \w*  # last part of "ecua..." 

    [^e]* # all that is not an "e" 
    (?: 
     \Be   # an "e" not at the start of a word 
     [^e]* 
     | 
     e(?!mbajada\b) # an "e" that is not the start of "embajada" 
     [^e]* 
    )*  # repeat as possible 
) # close the atomic group (backtracking is no more possible) 
embajada 

When the pattern fails
When the pattern succeeds

现在非贪婪的方法(同样的想法,以限制非贪婪量词的影响)

\becua(?>e*[^e]+)*?\bembajada\b 

When the pattern fails
When the pattern succeeds

+0

一句话:'\ w'会匹配'_'和数字,我认为'\ p {L}'是一个更好的替代品为'[a-zA-ZáéíóññÑÑääïöö]'。 –

+0

谢谢兄弟!有用!!我选择第二个正则表达式是因为更容易实现(我需要将用户插入的关键字转换为正则表达式)。 – Crabax

0

这是你在找什么对于? \b(ecua\w+) .*? (embajada)

+0

最差的答案得到了所有upvotes。 –

+1

这样的工作,但在失败的情况下,使117k步骤,用户评论一个正则表达式,在同一个案中使66k步骤 – Crabax

0

试验上regex101

执行下面是不同方法的比较表。第一个是我的,第二个是修改的OP'sregex,第三个是另一个用户在这里给出的答案的修改版本,第四个是Wiktor。不成功的比赛是为embajada错误embajad

+------+--------+--------+--------+--------+-------+------+--------------+ 
|    Regex      | Successful | Unsuccessful | 
+------+--------+--------+--------+--------+-------+------+--------------+ 
| \becua.*embajada       | 310 steps | 167543 steps | 

| \becua(?:.*)\b(.(?=embajada))*embajada | 993 steps | 579122 steps | 

| \becua.*?embajada      | 23897 steps | 167543 steps | 

| (?>\becua\p{L}*\b\s*\S*) 
| (?>(?:\s+(?!embajada)\S*)*)\s+embajada | 18001 steps | 111394 steps | 
+------+--------+--------+--------+--------+-------+------+--------------+ 

1日的正则表达式似乎需要在成功和不成功的比赛最少的步数

+1

您正在尝试我的模式从评论:)?尼斯。更好地显示来自http://regexhero.net/tester的测试。我的最新的'(?> \ becua \ p {L} * \ b \ s * \ S *)(?>(?:\ s +(?! embajada)\ S *)*)\ s + embajada'显示78,每秒2次迭代。 –

+0

@WiktorStribiżew即将更新 – rock321987

+1

请参阅Casimir的回答,研究该模式。比我的快三倍。 –