#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)
. Посмотрите эту демонстрацию регулярных выражений.