正则表达式捕获最后一个子模式

I'm trying to build a regex that will replace the tokens %aa% and %cc% inside a string. All the cases are listed below:

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%

I have the following regex which covers most of the case expect 2 and 5, basically those that contain the same chars as the tokens.

Regex pattern: %(?|(?|aa)|(?|cc))%(?=[^(aa|cc)]*($)+)

Language is PHP.

Thanks.

Your regex contains redundant branch reset groups ((?|...|...)) and the corrupt grouping that is placed into a character class [^(aa|cc)]*, and an end of string anchor quantified (($)+), which is also a user error (no need to capture the anchor here and it is enough to test it once).

You can use the following regex:

'~%(?:aa|cc)%(?!.*%(?:aa|cc)%)~'

See regex demo

For standalone strings, you can also add the ~s singleline (DOTALL) modifier: '~%(?:aa|cc)%(?!.*%(?:aa|cc)%)~s'.

The (?!.*%(?:aa|cc)%) negative lookahead fails a match if either aa or cc appear after the aa or cc found so far.