Почему более длинный токен в чередовании не будет сопоставлен?
Я использую ruby 2.1, но то же самое можно повторить на сайте Rubular.
Если это моя строка:
儘管中國婦幼衛生監測辦公室制定的
И я делаю регулярное выражение с этим выражением:
(中國婦幼衛生監測辦公室制定|管中)
Я ожидаю получить более длинный жетон в качестве матча.
中國婦幼衛生監測辦公室制定
Вместо этого я получаю второе чередование в качестве матча.
Насколько я знаю, это работает так, когда не на китайских иероглифах.
Если это моя строка:
foobar
И я использую это регулярное выражение:
(foobar|foo)
Возвращенный результат соответствия foobar
, Если порядок другой, то соответствующая строка foo
, Это имеет смысл для меня.
1 ответ
Ваше предположение, что регулярное выражение соответствует более длинному чередованию, неверно.
Если у вас есть немного времени, давайте посмотрим, как работает ваше регулярное выражение...
Быстрое освежение в памяти: как работает регулярное выражение: конечный автомат всегда читает слева направо, возвращаясь туда, где это необходимо.
Есть два указателя, один на Шаблон:
(cdefghijkl|bcd)
Другой на вашей строке:
abcdefghijklmnopqrstuvw
Указатель на строку перемещается слева. Как только он может вернуться, он будет:
http://gyazo.com/ac652df1ed094be6c5d66c14a2728ac1.png
Давайте превратим это в более "последовательную" последовательность для понимания:
http://gyazo.com/386aecb351fc2eb34f9c5db269a66dab.png
Ваш foobar
Пример это другая тема. Как я уже упоминал в этом посте:
Как работает регулярное выражение: конечный автомат всегда читает слева направо.
,|,, == ,
, так как он всегда будет соответствовать только первому чередованию.
Это хорошо, Юниэдр, но как мне заставить его к первому чередованию?
Смотри! *
^(?:.*?\Kcdefghijkl|.*?\Kbcd)
Здесь есть демонстрация регулярных выражений.
Это регулярное выражение сначала пытается сопоставить всю строку с первым чередованием. Только если он потерпит неудачу полностью, он попытается сопоставить второе чередование. \K
используется здесь, чтобы сохранить соответствие с содержимым позади конструкции \K
,
*
: \K
поддерживается в Ruby с 2.0.0.
Прочитайте больше:
Ах, мне было скучно, поэтому я оптимизировал регулярное выражение:
^(?:(?:(?!cdefghijkl)c?[^c]*)++\Kcdefghijkl|(?:(?!bcd)b?[^b]*)++\Kbcd)
Вы можете увидеть демо здесь.