Я пытаюсь создать регулярное выражение, которое заменит токены% aa% и% cc% внутри строки. Все случаи перечислены ниже:
1) /%aa%/%cc%/bb => should replace only %cc%
2) /%aa%/%cc%/ac => should replace only %cc%
3) /bb/%aa%/%cc% => should replace only the last %cc%
4) /bb/%aa% => should replace %aa%
5) /bb/ac/%aa%/%cc%/ac/bb => should replace only the last %cc%
У меня есть следующее регулярное выражение, которое охватывает большую часть случая, ожидая 2 и 5, в основном те, которые содержат те же символы, что и токены.
Regex pattern: %(?|(?|aa)|(?|cc))%(?=[^(aa|cc)]*($)+)
Язык - это PHP.
Благодарю.
В вашем регулярном выражении содержатся избыточные группы сброса ветвей ((?|...|...)
) и коррумпированная группировка, которая помещается в класс символов [^(aa|cc)]*
, и конец привязки строки количественно (($)+
), что также является ошибкой пользователя (нет необходимости фиксировать якорь здесь, и достаточно проверить его один раз).
Вы можете использовать следующее регулярное выражение:
'~%(?:aa|cc)%(?!.*%(?:aa|cc)%)~'
Для автономных строк вы также можете добавить модификатор ~s
singleline (DOTALL): '~%(?:aa|cc)%(?!.*%(?:aa|cc)%)~s'
.
Отрицательный lookahead (?!.*%(?:aa|cc)%)
не соответствует совпадению, если либо aa
либо cc
появляются после найденного aa
или cc
.
(?:...)
, они предназначены только для группировки, а не для захвата подтекстов. Это удобно, поскольку данные о совпадениях не переполняются ненужными подспариваниями.
%(?:aa|cc)%(?!.*%(?:aa|cc)%)
?