导致此RegExp中的无限循环的错误在哪里?

时间:2018-06-17 09:14:57

标签: javascript regex

以下是JS中的调用:

'Москва, Щёлковское шоссе д.3 строение 1 - Торговый Центр Город Хобби - 3 этаж, павильон 310, 105122'.match(/(?:[а-яА-ЯёЁ0-9\-\.\(\)]+\s?)+,?\s?(?:[а-яА-ЯёЁ0-9\-\.\(\)]+\s?)+(?:г|гор|город|п|пос|поселок|д|дер|деревня|ул|улица|пр|просп|пр-т|проспект|п|пл|площадь|ал|аллея|бул|б-р|дор|наб|пер|пр|пр-д|туп|ш|шос|шоссе|к|кор|корп|корпус|стр|строение|зд|зд-е|здание|вор|ворота|д|дом|секция)\.?\s?,?\s?(?:г|гор|город|п|пос|поселок|д|дер|деревня|ул|улица|пр|просп|пр-т|проспект|п|пл|площадь|ал|аллея|бул|б-р|дор|наб|пер|пр|пр-д|туп|ш|шос|шоссе|к|кор|корп|корпус|стр|строение|зд|зд-е|здание|вор|ворота|д|дом|секция)\.?\s?[а-яА-Я0-9ёЁ№\-\/()]+,?\s?(?:г|гор|город|п|пос|поселок|д|дер|деревня|ул|улица|пр|просп|пр-т|проспект|п|пл|площадь|ал|аллея|бул|б-р|дор|наб|пер|пр|пр-д|туп|ш|шос|шоссе|к|кор|корп|корпус|стр|строение|зд|зд-е|здание|вор|ворота|д|дом|секция)\.?\s?[а-яА-Я0-9ёЁ№\-\/()]+/gi)

它导致无限通话,因此控制台将被卡住。 我认为这里有问题,但找不到这个错误。

另外,我认为这不是V8中的错误,所以大家看看这个。 看起来瓶颈是导致在循环中搜索匹配的最后一部分[а-яА-Я0-9ёЁ№\-\/()]+

我该如何解决?

1 个答案:

答案 0 :(得分:2)

此问题称为catastrophic backtracking,由嵌套量词产生:

让我们减少这部分

(?:[а-яА-ЯёЁ0-9\-\.\(\)]+\s?)+

更具可读性:

(?:[0-9]+\s?)+

现在想象一下像12345这样的数字。上面的正则表达式有几个匹配的选项:

12345
1234, 5
123, 45
123, 4, 5
12, 345
12, 3, 45
12, 34, 5
12, 3, 4, 5
[...]
如果正则表达式最初不匹配,那么它必须尝试所有这些 - 毕竟,也许一个不同的组合可能会起作用,我们还没有尝试过。

因此,请避免嵌套量词,或确保它们不允许所有这些排列,例如不要使\s成为可选:

(?:[а-яА-ЯёЁ0-9\-\.\(\)]+\s)+

或将空格添加到角色类:

[а-яА-ЯёЁ0-9\-.()\s]+

不需要嵌套。