PHP preg_match_all并不匹配所有内容
考虑以下代码段:PHP preg_match_all并不匹配所有内容,php,regex,preg-match,preg-match-all,Php,Regex,Preg Match,Preg Match All,考虑以下代码段: $example = "DELIM1test1DELIM2test2DELIM1test3DELIM2test4"; // and so on preg_match_all('/DELIM1(.*?)DELIM2(.*?)/', $example, $matches); $matches数组变为: array:3 [ 0 => array:2 [ 0 => "DELIM1test1DELIM2" 1 => "DELIM1test3DEL
$example = "DELIM1test1DELIM2test2DELIM1test3DELIM2test4"; // and so on
preg_match_all('/DELIM1(.*?)DELIM2(.*?)/', $example, $matches);
$matches
数组变为:
array:3 [
0 => array:2 [
0 => "DELIM1test1DELIM2"
1 => "DELIM1test3DELIM2"
]
1 => array:2 [
0 => "test1"
1 => "test3"
]
2 => array:2 [
0 => ""
1 => ""
]
]
如您所见,它无法获取
test2
和test4
。为什么会发生这种情况?有什么可能的解决办法?谢谢。*?
不贪婪;如果后面没有约束,则它将匹配所需的最小值:零个字符。您需要在它之后添加一个约束,以强制它进行匹配。例如:
/DELIM1(.*?)DELIM2(.*?)(?=DELIM1|$)/
模式末尾的惰性子模式匹配0(
*?
)或1(+?
)个字符,因为它们匹配的字符尽可能少
您仍然可以使用延迟匹配并附加一个前瞻,该前瞻将要求DELIM1出现在值或字符串结尾之后:
/DELIM1(.*?)DELIM2(.*?)(?=$|DELIM1)/
看。就性能而言,它与(DELIM1(.*)DELIM2((?:(?!DELIM1)。*)非常接近。
-)
但是,最好的方法是展开它:
DELIM1(.*?)DELIM2([^D]*(?:D(?!ELIM1)[^D]*)*)
参见预分割会更好:
$example = "DELIM1test1DELIM2test2DELIM1test3DELIM2test4"; // and so on
$keywords = preg_split("/DELIM1|DELIM2/", $example,0,PREG_SPLIT_NO_EMPTY);
print_r($keywords);
输出:
Array
(
[0] => test1
[1] => test2
[2] => test3
[3] => test4
)
演示:您可以使用此负前瞻正则表达式:
preg_match_all('/DELIM1((?:(?!DELIM1|DELIM2).)*)DELIM2((?:(?!DELIM1|DELIM2).)*)/',
$example, $matches);
(?:(?!DELIM1 | DELIM2)。*
将匹配下一位置没有DELIM1
或DELIM2
的任何字符中的0个或多个
输出:
print_r($matches);
Array
(
[0] => Array
(
[0] => DELIM1test1DELIM2test2
[1] => DELIM1test3DELIM2test4
)
[1] => Array
(
[0] => test1
[1] => test3
)
[2] => Array
(
[0] => test2
[1] => test4
)
)
这些值不在您的锚定范围内,因此它们不会匹配。e、 g.(带有一些额外的空格)
(.*)
是非贪婪匹配,可以/将匹配0长度的字符串。由于M2
和te
之间的边界是一个0长度的字符串,因此该不可见的零长度字符匹配,模式终止于此
str: DELIM1 test1 DELIM2 test2 DELIM1 test3 DELIM2 test4
pat: DELIM1 (.*?) DELIM2 (.*?) DELIM1 (.*?) DELIM2 (.*?)
match #1 match #2