Учитывая две строки (обозначаемые 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 можно использовать для создания анимаций и игр на веб-страницах.
Ваша попытка регулярного выражения 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