Regex: сопоставить строку с предыдущим совпадением - PullRequest
0 голосов
/ 23 марта 2019

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

У меня есть такие строки:

Строка 1:

Interface123|HostVienna ~ Tunnel22 ~ CustomerA ~ ServiceA  ~ Vienna, Street 10|HostAmsterdam ~ Interface123 ~ CustomerB ~ ServiceA  ~ Amsterdam, Street 40|HostSarajevo ~ Interface12 ~ CustomerC ~ ServiceA ~ Sarajevo, Street 1040

Строка 2

Interface123|HostAmsterdam ~ Interface123 ~ CustomerB ~ ServiceA  ~ Amsterdam,Street 40

Я пытаюсь сделать одно регулярное выражение, которое может соответствовать всему от начала строки до "|" (слово) и используя это совпадение, я пытаюсь найти строку, разделенную "|" это содержит это слово. В моих примерах слово th Interface123.

Из любого приведенного выше примера результат должен быть:

HostAmsterdam ~ Interface123 ~ CustomerB ~ ServiceA  ~ Amsterdam,Street 40

Возможно ли это с чистым регулярным выражением?

Ответы [ 3 ]

1 голос
/ 23 марта 2019

Это возможно с обратными ссылками в regexp, хотя не каждая реализация поддерживает их. Что-то вроде:

^([^|]+)\|(?:[^|]*\|)*?([^|]*\1[^|]*)

Вторая группа захватит то, что вам нужно.

Объяснение: ^([^|]+)\| захватывает ваше ключевое слово, (?:[^|]*\|)*? соответствует нулю или более строк, окруженных '|' без ключевого слова, ([^|]*\1[^|]*) соответствует тому, что вам, наконец, нужно.

Демо

1 голос
/ 23 марта 2019

/^([^|]+)\|(?:[^|]+\|)*?\K[^|]*\b\1\b[^|]*/

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

Также важно включить совпадение в качестве первого, среднего или последнего набора данных в строке. Это важность (?:[^|]+\|)*?

Демо: https://regex101.com/r/7lMwZf/5

Разбивка:

^                     # start of string
([^|]+)\|             # capture needle then match first delimiting pipe
(?:[^|]+\|)*?         # match zero or more "sets of data"
\K[^|]*\b\1\b[^|]*    # forget previously matched characters with \K, then match set of data containing the needle until the end of string or first encountered pipe
0 голосов
/ 23 марта 2019

Вот шаблон, который, кажется, работает:

(?<=\||^)((?:(?!\|).)*Interface123.*?)(?=\||$)

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

(?<=\||^)       assert that what is prior is either pipe or the start of the string
((?:(?!\|).)*   consume anything so long is it is NOT pipe
Interface123.*? match 'Interface123` followed by anything up to
(?=\||$)        assert that what follows is either pipe or the end of the string

Демо

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

...