C# 如何不让正则表达式做太多的步骤?

C# 如何不让正则表达式做太多的步骤?,c#,regex,C#,Regex,我有一个简单的正则表达式(用于c#): 1) 以“ecua”开头的单词 2) 无论之后发生什么 3) “embajada”之后的单词“whatever” 但这会造成太多的步骤,我该如何防止呢?我只想让它通过字符,直到找到“embajada”这个词,而不是在每个字符上回溯。这看起来像是简单的正则表达式,但当我使用较大的文本时,当模式失败时,它会抛出灾难性的回溯(或超时) 例如: 提前谢谢这就是你要找的吗\b(ecua\w+).*?(embajada)这就是你要找的吗\b(ecua\w+).*?(e

我有一个简单的正则表达式(用于c#):

1) 以“ecua”开头的单词
2) 无论之后发生什么
3) “embajada”之后的单词“whatever”

但这会造成太多的步骤,我该如何防止呢?我只想让它通过字符,直到找到“embajada”这个词,而不是在每个字符上回溯。这看起来像是简单的正则表达式,但当我使用较大的文本时,当模式失败时,它会抛出灾难性的回溯(或超时)

例如:


提前谢谢

这就是你要找的吗<代码>\b(ecua\w+).*?(embajada)

这就是你要找的吗<代码>\b(ecua\w+).*?(embajada)

下面是不同方法的比较表。第一个是我的,第二个是修改的
OP的
regex
,第三个是另一个用户在这里给出的答案的修改版本,第四个是由
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 |
+------+--------+--------+--------+--------+-------+------+--------------+

第一个正则表达式似乎在成功和不成功的匹配中采取最少的步骤

下面是不同方法的比较表。第一个是我的,第二个是修改的
OP的
regex
,第三个是另一个用户在这里给出的答案的修改版本,第四个是由
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 |
+------+--------+--------+--------+--------+-------+------+--------------+

第一个正则表达式似乎在成功匹配和不成功匹配中采取的步骤最少

您可以用贪婪的方式编写模式,但这次使用原子组中的量词封闭所有部分。要做到这一点,您显然需要进行前瞻性测试,但为了限制过多测试的影响,您可以使用字符类(
[^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

现在是一种非贪婪的方法(限制非贪婪量词影响的相同想法):



您可以用贪婪的方式编写模式,但这次将所有部分用量词封装在一个原子组中。要做到这一点,您显然需要进行前瞻性测试,但为了限制过多测试的影响,您可以使用字符类(
[^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

现在是一种非贪婪的方法(限制非贪婪量词影响的相同想法):




你必须使用
(?=embajada)
而不是
(?!embajada)
,我想你的文本中没有“embajada”这个词,只有“gembajada”。我会展开它:不要太激动。先看看有什么问题。当你包含
\s+
时没有匹配,因为没有
\sembajada
,只有
\sgembajada
@WiktorStribiż如果没有匹配你必须使用
(?=embajada)
而不是
(?!embajada)
,我认为没有“embajada”这个词在你的文本中,只有“gembajada”。我会展开它:不要太激动。先看看有什么问题。当您包含
\s+
时,没有匹配项,因为没有
\sembajada
,只有
\sgembajada
@WiktorStribiż如果没有匹配项,它将导致
灾难性的回溯
。您正在从注释中尝试我的模式:)?美好的最好显示来自的测试。我最新的
(?>\becua\p{L}*\b\s*\s*)(?>(?:\s+(?!embajada)\s*))\s+embajada
显示每秒78,2次迭代。请参阅Casimir的答案,研究该模式。比我的快三倍。@WiktorStribiżew看起来像,
regexhero.net/tester
上的
analyze
功能只对专业人士可用users@WiktorStribiżew我没有得到基准选项中的任何内容。明天将检查它。您正在尝试我的评论模式:)?美好的最好显示来自的测试。我最新的
(?>\becua\p{L}*\b\s*\s*)(?>(?:\s+(?!embajada)\s*))\s+embajada
显示每秒78,2次迭代。请参阅Casimir的答案,研究该模式。比我的快三倍。@WiktorStribiżew看起来像,
regexhero.net/tester
上的
analyze
功能只对专业人士可用users@WiktorStribiżew我没有得到基准选项中的任何内容..我明天会检查它。注意:
\w
将匹配
\u
和数字,我认为
\p{L}
[a-zA-Záíóúñúñúëëöü]
的更好替代品。谢谢兄弟!!它起作用了!!我选择第二个正则表达式是因为它更容易实现(我需要将用户插入的关键字转换成正则表达式)。有一句话:
\w
将匹配
\u
和数字,我认为
\p{L}
[a-zA-Záíóúñëëöü]
的更好替代品。谢谢兄弟!!它起作用了!!我选择第二个正则表达式是因为它更容易实现(我需要将用户插入的关键字转换为正则表达式)。它可以工作,但失败时会执行117k个步骤。一个用户对一个正则表达式进行了注释,该正则表达式在相同情况下执行66k个步骤,但在失败时会执行117k个步骤,一个用户对一个在相同情况下执行66k步的正则表达式进行了注释