6

Мне нужно определить в строке одно из N заданных слов. Для примера возьмём такие: zero, .one, two

Частично с этим помогает справиться такое выражение:

/\b(?:zero|\.one|two)\b/

Но есть одна проблема: оно не определяет .one, так как оно начинается с не-word символа (.)

Как же должно выглядеть правильное выражение для данного случая?

MaxU - stand with Ukraine
  • 149,321
  • 12
  • 59
  • 132
Kir_Antipov
  • 4,642
  • И вне вопроса: посоветуйте хорошую литературу по регуляркам, пожалуйста. А то уже лет пять не доходят руки с ними разобраться от и до, так что их понимание у меня зиждется на моей интуиции хД – Kir_Antipov Nov 02 '18 at 03:35
  • https://karmazzin.gitbooks.io/eloquentjavascript_ru/ – Air Nov 02 '18 at 05:25
  • @Air: премного благодарен!) – Kir_Antipov Nov 02 '18 at 06:04
  • Всегда пожалуйста – Air Nov 02 '18 at 06:15
  • @Kir_Antipov, мне пока хватает погружения в регулярки того, что приводят в своей книге Албахари (C# X.X. Справочник. Полное описание языка) – Андрей NOP Nov 02 '18 at 07:08
  • @АндрейNOP: о, тоже верно) Я грешным делом всегда как-то пропускал главы про regex с мыслями: "Правильнее будет руками реализовать под конкретную задачу") Но вот, бывают задачи, где возможно использовать только регулярки ¯\(ツ) – Kir_Antipov Nov 02 '18 at 07:15
  • Всегда (наверное) можно заменить регулярку ручным парсингом, вопрос в том, во сколько раз становится запутаннее, сложнее и объемнее код. Хотя, с регулярками тоже можно такого наворотить... :D – Андрей NOP Nov 02 '18 at 07:26
  • @АндрейNOP: когда код полностью твой - безусловно. Поэтому я так посредственно к теме и относился. Но иногда от тебя как раз таки требуют не код, а регулярное выражение ¯\(ツ) – Kir_Antipov Nov 02 '18 at 07:27

1 Answers1

4

Дело в том, что регулярное выражение \b\.one\b может быть самопротиворечиво, т.к. граница слова здесь уже есть и она между точкой и буквой o: .one, это выражение сработает только если будет еще одна граница слова слева от точки, например: some.one, нужно ли вам это? Я не знаю.

Таким образом вам придется начать с чего-то вроде:

(?:\bzero\b|\.one\b|\btwo\b)

и потом, возможно, добавить отрицательный просмотр назад:

(?:\bzero\b|(?<!\b)\.one\b|\btwo\b)

ну и в итоге можно будет немного сократить до чего-то вроде:

(?:\b(zero|two)|(?<!\b)\.one)\b

тест: https://regex101.com/r/IkeH4m/1