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

Учитывая две строки (обозначаемые 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. Еще одно отличие состоит в том, что мне не нужно проверять, содержит ли внутренняя часть указанную строку.

regex101.com/r/AJzqWp/1
Wiktor Stribiżew 05.09.2024 07:46

@WiktorStribiżew: нет необходимости проверять ec посередине. А в вашем регулярном выражении я не понимаю назначения b?.

lyrically wicked 05.09.2024 08:16

Как объяснить, почему R возвращается false?

lyrically wicked 05.09.2024 08:18

Если вам не нужно проверять наличие ec внутри, это еще проще, ab(?!(?:a|cb|cd|ab|bc).)*bc. Вам необходимо включить начальный и конечный разделители в просмотр вперед. Все еще дубликат, вам просто нужен закаленный жадный жетон

Wiktor Stribiżew 05.09.2024 09:07

@WiktorStribiżew Помимо отсутствующей внешней группы в вашем регулярном выражении, использование смягченного жадного токена приведет к ложноотрицательным результатам, когда то, что находится между A и B, соответствует одному из N путем перекрытия с B, что нарушает правило ОП «эта часть не перекрывается с A». и Б». Например, abcbc должен совпадать, потому что c не является ни одним из a, cb и cd, но при вашем подходе он не будет совпадать, потому что cb пересекается с bc. Демо: regex101.com/r/NqLbfV/5

blhsing 05.09.2024 09:50

@blhsing Здесь нет необходимости в какой-либо внешней группе. И ваше регулярное выражение в ответе дает те же три совпадения, что и регулярное выражение ab(?:(?!a|cb|cd|ab|bc).)*bc.

Wiktor Stribiżew 05.09.2024 10:02

@WiktorStribiżew К сожалению, я опубликовал не ту демо-версию. Отсутствуя внешнюю группу, я имел в виду опубликованное вами регулярное выражение ab(?!(?:a|cb|cd|ab|bc).)*bc, которое вы теперь исправили, правильно сделав группу без захвата внешней группой. Демонстрация указанного ложноотрицательного результата с вашим регулярным выражением: regex101.com/r/M3EgpH/1 И демонстрация сопоставления того же ввода с моим регулярным выражением: regex101.com/r/M3EgpH/2

blhsing 05.09.2024 10:08

Я не понимаю роль |ab|bc в ab(?:(?!a|cb|cd|ab|bc).)*bc.

lyrically wicked 05.09.2024 10:15

@lyricalwicked Включение |ab|bc в отрицательный просмотр вперед предотвращает появление A и B между A и B . Это еще один способ провести нежадное сопоставление.

blhsing 05.09.2024 10:26

@blhsing: Но я не упомянул, что мне нужно нежадное совпадение: на самом деле жадное совпадение было бы предпочтительнее. И "0abbc1ab2bc3ababc4abcbbc5ab6bc7".match(/ab(?:(?!a|cb|cd).)*‌​bc/g) дает те же три совпадения, значит, это регулярное выражение тоже решает проблему?

lyrically wicked 05.09.2024 10:40

@lyricallywicked Верно, но опять же, если вы не хотите соблюдать свое правило «эта часть не пересекается с A и B». Демонстрация вашего жадного регулярного выражения, не соответствующего моему образцу ввода abcbc: regex101.com/r/M3EgpH/3

blhsing 05.09.2024 10:49
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
11
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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

Как написать регулярное выражение R такое, чтобы, например, "0abbc1ab2bc3ababc4abcbbc5ab6bc7".match(R) возвращало ["abbc", "ab2bc", "ab6bc"]? Я использовал вариант в ответе как /(ab(?=.*(bc.*))(?!.*(?:a|cb|cd).*\1))/g, но он возвращает [ "ab" ].

lyrically wicked 05.09.2024 09:15

Вы можете просто включить .*?bc в шаблон. Тогда я обновил ответ соответственно.

blhsing 05.09.2024 09:20

Если возможно, добавьте более подробное объяснение R: я не понимаю, почему он «по сути соответствует только abcd, пока нет a, cb и cd после ab».

lyrically wicked 05.09.2024 09:51

Тогда я перефразировал свои объяснения. Надеюсь, теперь стало яснее.

blhsing 05.09.2024 10:01

Другие вопросы по теме

Похожие вопросы