为什么这段代码卡住了node.js - Javascript上的Bug?

时间:2016-02-17 10:58:02

标签: javascript regex node.js unicode infinite-loop

我试图运行这个正则表达式,但它卡住了我的控制台。为什么呢?

var str = "Шедевры православной музыки - 20 золотых православных песен";
str.match(/^(([\u00C0-\u1FFF\u2C00-\uD7FF]+[^a-z\u00C0-\u1FFF\u2C00-\uD7FF]*)+) [a-z]+[^\u00C0-\u1FFF\u2C00-\uD7FF]*$/i);

1 个答案:

答案 0 :(得分:8)

由于(([\u00C0-\u1FFF\u2C00-\uD7FF]+[^a-z\u00C0-\u1FFF\u2C00-\uD7FF]*)+)部分,您的正则表达式导致catastrophic backtracking(请参阅a demo of your regex here)。由于[^a-z\u00C0-\u1FFF\u2C00-\uD7FF]*可以匹配零个字符,因此您基本上有一个类似于(a+)+的经典模式(cf:([\u00C0-\u1FFF\u2C00-\uD7FF]+)+)会导致回溯问题。

要摆脱它,您需要确保子模式在分组中是必修,并将*量词应用于整个分组:

^([\u00C0-\u1FFF\u2C00-\uD7FF]+(?:[^a-z\u00C0-\u1FFF\u2C00-\uD7FF]+[\u00C0-\u1‌​FFF\u2C00-\uD7FF]+)*) [a-z]+[^\u00C0-\u1FFF\u2C00-\uD7FF]*$

请参阅regex demo

此处[\u00C0-\u1FFF\u2C00-\uD7FF]+(?:[^a-z\u00C0-\u1FFF\u2C00-\uD7FF]+[\u00C0-\u1‌​FFF\u2C00-\uD7FF]+)*匹配:

  • [\u00C0-\u1FFF\u2C00-\uD7FF]+ - [\u00C0-\u1FFF\u2C00-\uD7FF]范围内的一个或多个字符
  • (?:[^a-z\u00C0-\u1FFF\u2C00-\uD7FF]+[\u00C0-\u1‌​FFF\u2C00-\uD7FF]+)* - 零个或多个序列:
    • [^a-z\u00C0-\u1FFF\u2C00-\uD7FF]+ - 除a-z\u00C0-\u1FFF\u2C00-\uD7FF范围
    • 以外的一个或多个字符
    • [\u00C0-\u1‌​FFF\u2C00-\uD7FF]+ - \u00C0-\u1‌​FFF\u2C00-\uD7FF范围内的一个或多个字符。