Парсинг нескольких имен - Lookhehind в середине регулярного выражения не работает - PullRequest
0 голосов
/ 11 мая 2018

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

Желаемый результат:

Произведите следующее с помощью регулярных выражений:

"Person One"
"Person Two"
"Person Three"

Из этих строк примера:

By Person One, Person Two and Person Three
By Person One, Person Two
By Person One
By Person Two and Person Three

Вот что у меня есть, и обратите внимание, что если вы прервете разделы, я получу частичное совпадение, но что-то со взглядом назад отбрасывает его. Кроме того, если есть более простой способ, но все же надежный, вытащить всех «людей», независимо от того, предоставляется ли один, два или три с «и». Он не должен поддерживать больше трех, но я думаю, что до тех пор, пока следы "и" продолжаются, число "людей" может оставаться переменным, не влияя на регулярное выражение.

Сохраненная текущая попытка (соответствует одной, но если вы разделите my и lookbehind и запустите ее, то она совпадет со всеми строками "и":

(?<=by )((\w+) (\w+))(?:,\s*)?((\w+) (\w+))?(?:\s*(?<=and ))((\w+) (\w+))

https://regex101.com/r/z3Y9TQ/1

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Я не могу заставить работать and, но это работает с группой без захвата:

(?<=by )(\w+ \w+)(?:, *)?(\w+ \w+)?(?: *)(?:and (\w+ \w+))?

Я изменил \s на пробел в регулярном выражении, чтобы он не совпадал с символами новой строки.

DEMO

0 голосов
/ 11 мая 2018

Вместо использования Lookbehind для проверки and вы можете использовать группу без захвата, как то, что вы делали с запятой:

(?<=by )(\w+ \w+)(?:,\s*)?(\w+ \w+)?(?:\sand\s)?(\w+ \w+)?

Обратите внимание, что вам не нужно добавлять каждый \w+ в группе.

Попробуйте онлайн .


Посмотрите за середину регулярного выражения:

Причина, по которой Lookbehind не будетработа в этом случае заключается в том, что у вас есть это в середине вашего шаблона регулярных выражений.Это не то, как работает Lookbehind.Сопоставление начинается с начала до тех пор, пока не достигает Сзади (например, (?<=prior)subsequent), оно соответствует тому, что следует за ним (т. Е. subsequent), затем и только затем ."смотрит за спиной", ожидая найти prior.Таким образом, в основном за тем, что предшествует Lookbehind, должно следовать то, что следует за (?<=) (то есть subsequent), но в то же время , то, что следует за Lookbehind, должно бытьпредшествует то, что внутри него (т. е. prior).Видите, откуда возникла проблема?

Поэтому, в вашем примере, единственный способ сопоставить полное предложение со взглядом сзади в середине - это также включить and в шаблон , который делаетВзгляд за резервом .

Для иллюстрации взгляните на это демо .Как видите, шаблон ((?<=and )Person соответствует Person, когда он идет после and.Теперь давайте изменим его на Two (?<=and )Person, вы, вероятно, подумаете, что он будет работать, но на самом деле не находит совпадений , и это потому, что сначала он ищет Two, а затем Person,но он не находит его (потому что «Персона» не следует сразу за «двумя») , поэтому он не переходит к следующему шагу, который является Смотрителем.

Единственныйспособ заставить Lookbehind работать в этом случае, это также включить and сразу после Two, как это: Two and (?<=and )Person, что делает Lookbehind избыточным, как объяснено выше.

Подобное поведение, но для Lookaheads (то есть, когда Lookahead идет посередине) очень хорошо объяснено в этот удивительный ответ be revo.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...