Consider next example:
$payload = '
ababaaabbb =%=
ababaaabbb =%=
ababaa =%=
';
$pattern = '/^[ab]+\s*(?:=%=)?$/m';
preg_match_all($pattern, $payload, $matches);
var_dump($matches);
Expected and actual result of match is:
"ababaaabbb =%="
"ababaaabbb =%="
"ababaa =%="
But if $payload
changed to
$payload = '
ababaaabbb =%=
ababaaabbb =%=
ababaa =%'; // "=" sign removed at EOL
actual result is
"ababaaabbb =%="
"ababaaabbb =%="
but expected is
"ababaaabbb =%="
"ababaaabbb =%="
"ababaa "
Why this happen? Group (?:=%=)?
is optional due to ?
and last string in payload should be also present in match results.
The group
(?:=%=)?
is optional in your regular expression. That does not mean each part of that group is also optional.Your regex works only if it sees a string of
a
s andb
s, optional whitespace, then either (1)=%=
and the end of the line or (2) just the end of the line. It will not work if it sees a string ofa
s andb
s, whitespace, then anything other than exactly=%=
or the end of the line. So,=%
won't work.To accomplish what you apparently want to do, you need to make the second
=
optional, like so:But it seems like you don't want the
=%
at all in this scenario, which means you need to get more creative still:Demo.
Have a look at your current regex graph:
The
=%=
is optional (see how the branch betweenwhite space
andEnd of line
forks), but the EOL is required. That means after one or morea
orb
symbols, and zero or more whitespaces, EOL must occur. However, you have=%
on your 3rd line => NO MATCH.Now, when you move the
$
anchor into the optional group:The end of line is now optional, too, and the match will be returned after matching 1+
a
orb
chars and optional whitespaces.Since last line is ending with
=%
, you should make last=
optional as well and use a capturing group for your expected data:RegEx Demo
PS: Your expected result is available in captured group #1