带有可选组的正则表达式多行模式跳过有效数据
Regex multiline mode with optional group skip valid data
考虑下一个例子:
$payload = '
ababaaabbb =%=
ababaaabbb =%=
ababaa =%=
';
$pattern = '/^[ab]+\s*(?:=%=)?$/m';
preg_match_all($pattern, $payload, $matches);
var_dump($matches);
比赛的预期和实际结果是:
"ababaaabbb =%="
"ababaaabbb =%="
"ababaa =%="
但是如果$payload
改为
$payload = '
ababaaabbb =%=
ababaaabbb =%=
ababaa =%'; // "=" sign removed at EOL
实际结果是
"ababaaabbb =%="
"ababaaabbb =%="
但预期是
"ababaaabbb =%="
"ababaaabbb =%="
"ababaa "
为什么会这样?由于 ?
,组 (?:=%=)?
是可选的,有效负载中的最后一个字符串也应出现在匹配结果中。
由于最后一行以 =%
结尾,您也应该将最后 =
设为可选,并为您的预期数据使用捕获组:
/^([ab]+\s*)(?:=%=?)?$/m
PS: 您的预期结果在捕获组 #1
中可用
组 (?:=%=)?
在您的正则表达式中是可选的。 并不意味着该组的每个部分也是可选的。
你的正则表达式只有在看到 a
s 和 b
s 的字符串,可选的空格,然后是 (1) =%=
和行尾或 ( 2)只是行尾。如果它看到 a
和 b
的字符串,空格,然后是 =%=
或行尾以外的任何内容,它将不起作用。所以,=%
不会起作用。
要完成您显然想做的事情,您需要将第二个 =
设为可选,如下所示:
$pattern = '/^[ab]+\s*(?:=%=?)?$/m';
// see the additional ? here^
但在这种情况下,您似乎根本不想要 =%
,这意味着您还需要发挥更多创意:
$pattern = '/^[ab]+\s*(?:(?:=%=)?$|(?==%$))/m';
Demo.
查看您当前的正则表达式图表:
=%=
是 可选的(查看 white space
和 End of line
之间的分支如何分支),但是 EOL 是必需的 。这意味着 在一个或多个 a
或 b
符号以及零个或多个空格之后,EOL 必须出现 。但是,您的第 3 行有 =%
=> 不匹配。
现在,当您将 $
锚移到可选组时:
行尾现在也是 optional,匹配 1+ a
或 b
个字符和可选空格后将返回匹配.
考虑下一个例子:
$payload = '
ababaaabbb =%=
ababaaabbb =%=
ababaa =%=
';
$pattern = '/^[ab]+\s*(?:=%=)?$/m';
preg_match_all($pattern, $payload, $matches);
var_dump($matches);
比赛的预期和实际结果是:
"ababaaabbb =%="
"ababaaabbb =%="
"ababaa =%="
但是如果$payload
改为
$payload = '
ababaaabbb =%=
ababaaabbb =%=
ababaa =%'; // "=" sign removed at EOL
实际结果是
"ababaaabbb =%="
"ababaaabbb =%="
但预期是
"ababaaabbb =%="
"ababaaabbb =%="
"ababaa "
为什么会这样?由于 ?
,组 (?:=%=)?
是可选的,有效负载中的最后一个字符串也应出现在匹配结果中。
由于最后一行以 =%
结尾,您也应该将最后 =
设为可选,并为您的预期数据使用捕获组:
/^([ab]+\s*)(?:=%=?)?$/m
PS: 您的预期结果在捕获组 #1
中可用组 (?:=%=)?
在您的正则表达式中是可选的。 并不意味着该组的每个部分也是可选的。
你的正则表达式只有在看到 a
s 和 b
s 的字符串,可选的空格,然后是 (1) =%=
和行尾或 ( 2)只是行尾。如果它看到 a
和 b
的字符串,空格,然后是 =%=
或行尾以外的任何内容,它将不起作用。所以,=%
不会起作用。
要完成您显然想做的事情,您需要将第二个 =
设为可选,如下所示:
$pattern = '/^[ab]+\s*(?:=%=?)?$/m';
// see the additional ? here^
但在这种情况下,您似乎根本不想要 =%
,这意味着您还需要发挥更多创意:
$pattern = '/^[ab]+\s*(?:(?:=%=)?$|(?==%$))/m';
Demo.
查看您当前的正则表达式图表:
=%=
是 可选的(查看 white space
和 End of line
之间的分支如何分支),但是 EOL 是必需的 。这意味着 在一个或多个 a
或 b
符号以及零个或多个空格之后,EOL 必须出现 。但是,您的第 3 行有 =%
=> 不匹配。
现在,当您将 $
锚移到可选组时:
行尾现在也是 optional,匹配 1+ a
或 b
个字符和可选空格后将返回匹配.