具有可选组跳过有效数据的正则表达式多线模式

时间:2017-02-08 18:55:59

标签: php regex preg-match-all pcre multiline

考虑下一个例子:

let init n ~f =
  if n < 0 then raise (Invalid_argument "init");
  let rec loop i accum =
    if i = 0 then accum
    else loop (i-1) (f (i-1) :: accum)
  in
  loop n []
;;

匹配的预期和实际结果是:

$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 " ,组(?:=%=)?是可选的,有效负载中的最后一个字符串也应出现在匹配结果中。

3 个答案:

答案 0 :(得分:1)

查看当前的正则表达式图:

enter image description here

=%= 是可选的(请参阅white spaceEnd of line分叉之间的分支),但需要EOL 。这意味着在一个或多个ab符号之后,以及零个或多个空格,必须出现EOL 。但是,您的第3行有=% =&gt;没有比赛。

现在,当您将$锚点移动到可选组中时:

enter image description here

行尾也是可选,匹配1 + ab字符和可选空格后会返回匹配。

答案 1 :(得分:0)

由于最后一行以=%结尾,因此您应该将最后一个=设为可选,并为您的预期数据使用捕获组:

/^([ab]+\s*)(?:=%=?)?$/m

[2]

PS:您的预期结果在捕获的组#1中可用

答案 2 :(得分:0)

小组(?:=%=)?在正则表达式中是可选的。 意味着该组的每个部分也是可选的。

你的正则表达式只有在它看到一串a s和b s,可选空格,然后是(1)=%=和行尾或(2)时才有效只是结束了。如果它看到一串a s和b s,空格,那么除了=%=以外的任何内容或该行的结尾都不会起作用。因此,=%无法工作。

要完成您显然想做的事情,您需要使第二个=可选,如下所示:

$pattern = '/^[ab]+\s*(?:=%=?)?$/m';
// see the additional ? here^

但在这种情况下,您似乎并不想要=% ,这意味着您需要获得更多创意:

$pattern = '/^[ab]+\s*(?:(?:=%=)?$|(?==%$))/m';

Demo