我正在尝试运行此正则表达式,但它卡住了我的控制台。为什么?

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

最佳答案

由于(([\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范围中的一个或多个字符。
  • 07-24 19:54