2016-02-11 3 views
0

Я пытаюсь понять, почему это возвращает ложь, и что я могу сделать, чтобы сделать это правдой.JS RegExp() для поиска вхождений

var str = "The best things in life are free"; 
var patt = new RegExp(/(?=best)(?=life)/i); 
var res = patt.test(str); // = false. But expect true because both 'best' and 'life' are in the string 
+0

@ WiktorStribiżew Что такое дубликат об этом? –

+1

Ваше регулярное выражение (/ (? = Best) (? = Life) /) скажет, что НИЧЕГО не стоит, что перед этим есть «лучшая жизнь»! – nAviD

+0

Чего вы действительно хотите достичь? – nAviD

ответ

1

Проблема заключается в том, что ваши lookaheads требуют best и life быть в том же положении, в строке. Взгляды вперед - это утверждения с нулевой шириной и не продвигают индекс RegExp. Таким образом, ваш /(?=best)(?=life)/i проверяет в каждом положении (если вы перемещаете lastIndex вручную в коде), если за ним следует bestиlife.

Использование

/^(?=.*best)(?=.*life)/i 

Это регулярное выражение потребует best и life присутствовать на любой месте внутри строки.

var str = "The best things in life are free"; 
 
var patt = /^(?=.*best)(?=.*life)/i; 
 
var res = patt.test(str); 
 
document.body.innerHTML = res;

Почему /^(?=.*best)(?=.*life)/i но не /(?=.*best)(?=.*life)/i?

При отсутствии привязки в каждом положении выполняются наблюдения. Когда мы устанавливаем ^ в начале, два вида выполняются один за другим (если предыдущему удалось). Производительность намного лучше, когда вы выполняете их только один раз. В этом случае, однако, нет разницы, поскольку в регулярном выражении нет модификатора /g.

Почему не /best.*life|life.*best/?

Возможно, для этого потребуется чередование, и в случае, если у вас много таких альтернатив, его будет сложнее поддерживать.

Почему бы не использовать .indexOf?

Потому что следующий возможно повышение является соответствие два слова как целые слова:

/^(?=.*\bbest\b)(?=.*\blife\b)/i 

Так, чтобы не соответствовать bestie или afterlife.

И последнее, но не менее примечание: если ваша строка может содержать строку, заменить .* с [\s\S]*, так как точка в регулярном выражении JS не может совпадать с символом новой строки.

+1

@BobvanLuijt: У вас нет модификатора '/ g', поэтому оба' /(?=.* best) (? =. * Life)/i' и '/^(?=.*best)(?=. * life)/i' должен работать одинаково (поскольку строка обрабатывается слева направо). –

+0

И хорошо, что у вас нет '/ g', потому что вы [не должны использовать'/g' с 'RegExp # test()'] (http: // stackoverflow.ком/вопросы/1520800/почему-регулярное выражение-с-ГЛОБАЛ-флаг-в-JavaScript-дать-неправильные результаты) –

Смежные вопросы