Использование регулярного выражения для поиска нескольких совпадений между двумя строками

#regex #pcre #between

#регулярное выражение #pcre #между

Вопрос:

Представьте, что у меня есть такая строка:

c x c x A c x c x c B c x c x

И я хочу найти любой символ «c», который находится между «A» и «B». Итак, в этом примере мне нужно получить 3 совпадения.

Я знаю, что могу использовать токены lookahead и lookbehind. Итак, я использовал это регулярное выражение:

(?<=A).*c.*(?=B)

Но он получает все жало между A и B: c x c x c как один результат.

И если я удалю .* части, совпадений вообще не будет.

Я привел здесь пример. итак, вы можете видеть результаты.

Комментарии:

1. Например (?:G(?!^)|A)[^AB]*?Kc(?=.*?B) , см. regex101.com/r/TeHHiF/1 . Если A и B являются заполнителями для строк с несколькими символами, используйте (?:G(?!^)|A)(?:(?!A).)*?Kc(?=.*?B) ( демо )

2. Вау! @WiktorStribizew Ты волшебник! Большое спасибо. Пожалуйста, отправьте свой комментарий в качестве ответа, чтобы я мог пометить его как ответ.

Ответ №1:

Здесь есть два распространенных сценария: 1) A и B разные строки из одного символа, 2) A и B разные строки с разными символами.

Сценарий 1

Вы можете использовать отрицаемые классы символов:

 (?:G(?!^)|A)[^AB]*?Kc(?=[^AB]*B)
 

Посмотрите эту демонстрацию регулярных выражений. Подробные сведения:

  • (?:G(?!^)|A) A или конец предыдущего успешного совпадения
  • [^AB]*? — любые нулевые или более символов, кроме A и B , как можно меньше
  • K — оператор сброса соответствия, который отбрасывает весь текст, сопоставленный до сих пор в общем буфере соответствия памяти
  • c c символ / строка
  • (?=[^AB]*B) — за этим должно следовать ноль или более символов, отличных от A и B , а затем B сразу справа от текущего местоположения.

Сценарий 2

Если A и B являются заполнителями для строк с несколькими символами, скажем, ABC и BCE и c является некоторым шаблоном, например cd (для сопоставления c и одной или нескольких цифр после него), используйте

 (?s)(?:G(?!^)|ABC)(?:(?!ABC).)*?Kcd (?=.*?BCE)
 

Посмотрите эту демонстрацию регулярных выражений. Подробные сведения:

  • (?s) — модификатор DOTALL, который заставляет механизм регулярных выражений сопоставлять любой символ с .
  • (?:G(?!^)|ABC) ABC или конец предыдущего успешного совпадения
  • (?:(?!ABC).)*? — любой символ, 0 или более раз, который не запускает последовательность ABC символов
  • K — оператор сброса соответствия
  • cd c и одна или несколько цифр
  • (?=.*?BCE) — любые нулевые или более символов, как можно меньше, за которыми следует BCE символ .

Комментарии:

1. Отличное решение! Кажется, мы можем использовать simple .*? вместо (?:(?!ABC).)*? , поскольку мы не беспокоимся о других возможных ABC ‘s между первым ABC и c .

2. Это здорово. Большое вам спасибо. Но есть небольшой дефект. Если строка была c x c x ABC c1 x c2 x c3 BCE c4 x c5 x BCE c4 и c5 также будет в результатах. Я изменил (?:(?!ABC).)*? часть на (?:(?!BCE).)*? и проблема решена. Но все же будет еще одна проблема, если бы у нас была эта строка: ABC c0 x ABC c1 x c2 x c3 BCE c4 x c5 x BCE c0 она тоже будет в результатах. Я не мог понять это.

3. @MohsenHaeri Добавьте оба разделителя в предварительный просмотр, (?s)(?:G(?!^)|ABC)(?:(?!ABC|BCE).)*?Kcd (?=(?:(?!ABC).)*BCE) . Посмотрите эту демонстрацию регулярных выражений.