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

Учитывая две строки (обозначаемые A и B) и набор N строк, мне нужно написать регулярное выражение, чтобы проверить, содержит ли данная входная строка W подстроку S, где S — любая подстрока, которая удовлетворяет всем следующим трем условиям. : 1. начинается с буквы А; 2. заканчивается на B; 3. ни один элемент N не встречается в части между А и В (эта часть не пересекается с А и В).

Например, я выбрал "ab" в качестве A, "bc" в качестве B, ["a", "cb", "cd"] в качестве N. Если "ec" — внутренняя часть, то "abecbc" — это строка, удовлетворяющая всем трем условиям: если W содержит такую ​​подстроку, регулярное выражение должно вернуть true. Мой первый вариант — это следующее регулярное выражение:

var T = /(?=ab.*bc)(?=(?!ab.*a.*bc))(?=(?!ab.*cb.*bc))(?=(?!ab.*cd.*bc))/;  

Я выбрал W = S = "abecbc". Это регулярное выражение работает так, как ожидалось:

T.test("abecbc");
// true

Но меня интересует следующая проблема: как написать функционально эквивалентное регулярное выражение, не используя положительный просмотр (?=)в качестве оператора AND?

Итак, мой второй вариант следующий:

var R = /ab(?!.*?(?:a|cb|cd).*)bc/;

Но R.test("abecbc") оценивается как false. Итак, разделим R на три части:

/ab(.*)/.test("abecbc")

возвращается true. Затем

/(.*)bc/.test("abecbc")

возвращается true.

Внутренняя часть (т. е. часть между "ab" и "bc") — это "ec". И

/(?!.*?(?:a|cb|cd).*)/.test("ec")

возвращает true, что и ожидалось. Значит, истин должно быть три, и частей в R больше нет. Тогда почему

/ab(?!.*?(?:a|cb|cd).*)bc/.test("abecbc")

оценить на false? И как написать правильное регулярное выражение, решающее проблему, описанную в первом абзаце поста, не используя положительный просмотр (?=)в качестве оператора AND?

РЕДАКТИРОВАТЬ

Мой вопрос не является дубликатом этого вопроса: мне нужно объяснение, почему конкретное регулярное выражение (R) возвращает false вместо true. Еще одно отличие состоит в том, что мне не нужно проверять, содержит ли внутренняя часть указанную строку.

🤔 А знаете ли вы, что...
JavaScript можно использовать для создания анимаций и игр на веб-страницах.


50
1

Ответ:

Решено

Ваша попытка регулярного выражения R = /ab(?!.*?(?:a|cb|cd).*)bc/ не соответствует abecbc, потому что шаблон отрицательного просмотра представляет собой утверждение нулевой ширины, поэтому за вашим регулярным выражением bc должно немедленно следовать ab. И если вы попытаетесь исправить это, добавив .* перед bc, то нет никакой гарантии, что совпадение a|cb|cd произойдет между ab и bc.

Вместо этого вы можете захватить B и то, что следует за ним, чтобы вы могли использовать захват в качестве окончания в утверждении отрицательного просмотра вперед, чтобы избежать совпадения, когда между A и B есть какое-либо из N:

ab(?=.*?(bc.*))(?!.*(?:a|cb|cd).*\1).*?bc

Демо: https://regex101.com/r/NqLbfV/4


Интересные вопросы для изучения

В файле location.href намеренно отсутствуют имя пользователя и пароль при включении в URL-адрес?Расширение не загружается в коде Visual Studio — сообщения об отладке не отображаютсяКак добавить учащегося (@gmail.com) в класс Classroom, созданный внутри моей организации с помощью Apps Script?При использовании parseFloat невозможно вычислить сумму более 1 миллионаИспользуйте предопределенный массив строковых значений для querySelectorAll, чтобы выполнить определенное действиеRegex: сопоставить кратчайший шаблон между двумя возможными разделителямиИспользованиеdependent_wider_regex для создания новой строки для каждого совпадения в RДобавить новые строки перед выбранными символами дефисаНаписание Regex для обработки дополнительных символов с плавающей запятой в начале строки?Как извлечь из строки только уникальные значения, используя регулярное выражение в Python?