我正在尝试匹配%s中包含的子字符串,但preg_match_all
似乎在同一行中同时包含多个子字符串。
代码如下所示:
preg_match_all("/%.*%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches);
print_r($matches);
产生以下输出。
Array
(
[0] => Array
(
[0] => %hey%_thereyou're_a%rockstar%
[1] => %there%
)
)
但是我希望它能产生以下数组:
[0] => %hey%
[1] => %rockstar%
[2] => %there%
我错过了什么?
答案 0 :(得分:12)
将正则表达式中的“.
”替换为“[^%]
”:
preg_match_all("/%[^%]*%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches);
正在发生的事情是“.
”尽可能地“贪婪”地匹配,包括一切直到最后的%。用否定的字符类“[^%]
”替换它意味着它将匹配除百分比之外的任何,这将使它与您想要的位匹配。
另一个选择是在点后放置一个“?
”,告诉它“不要贪婪”:
preg_match_all("/%.*?%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches);
在上面的例子中,任何一个选项都可以使用,但是有时你可能会搜索大于单个字符的东西,所以否定的字符类将无济于事,所以解决方案就是不要贪图匹配。
答案 1 :(得分:4)
你正在做一场贪婪的比赛 - 使用?
让它不合时宜:
/%.*?%/
如果匹配内可能出现换行符,请添加s(DOTALL)修饰符:
/%.*?%/s
答案 2 :(得分:2)
添加?在*:
之后preg_match_all("/%.*?%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches);
答案 3 :(得分:1)
原因是明星贪婪。也就是说,星号使正则表达式引擎尽可能频繁地重复前面的标记。你应该试试 。*?代替。
答案 4 :(得分:1)
您可以尝试/%[^%]+%/
- 这意味着在百分号之间您只想匹配不是百分号的字符。
您也可以将模式设为不合适,例如: /%.+%/U
,所以它会尽可能少地捕捉(我认为)。
答案 5 :(得分:1)
|%(\ W +)%|这将完全符合您的要求。