请考虑以下代码段:
$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
。出现这种情况的原因和可能的解决方案是什么?谢谢。
答案 0 :(得分:3)
.*?
不贪心;如果你之后没有约束,它将匹配必要的最小值:零个字符。你需要一个约束来强迫它匹配更多。例如:
/DELIM1(.*?)DELIM2(.*?)(?=DELIM1|$)/
答案 1 :(得分:3)
preg_split会更好:
$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
)
答案 2 :(得分:2)
模式结尾处的懒惰子模式匹配0(*?
)或1(+?
)个字符,因为它们匹配的数量尽可能少。
你仍然可以使用延迟匹配并追加一个前瞻,它需要DELIM1出现在字符串的值或结尾之后:
/DELIM1(.*?)DELIM2(.*?)(?=$|DELIM1)/
见demo。 tempered greedy token(DELIM1(.*?)DELIM2((?:(?!DELIM1).)*)
- demo)在性能方面非常接近。
然而,最好的方法是展开它:
DELIM1(.*?)DELIM2([^D]*(?:D(?!ELIM1)[^D]*)*)
请参阅another demo
答案 3 :(得分:2)
这些值是您的锚点的外部,因此它们不会匹配。例如(有一些额外的空格)
str: DELIM1 test1 DELIM2 test2 DELIM1 test3 DELIM2 test4
pat: DELIM1 (.*?) DELIM2 (.*?) DELIM1 (.*?) DELIM2 (.*?)
match #1 match #2
(.*?)
是非贪婪的匹配,可以/将匹配0长度的字符串。由于M2
和te
之间的边界是一个0长度的字符串,因此该不可见的零长度字符匹配,并且该模式在那里终止。
答案 4 :(得分:0)
您可以使用此负前瞻性正则表达式:
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
)
)