正则表达式匹配%之间的字符串

时间:2009-08-13 08:05:15

标签: php regex preg-match-all

我正在尝试匹配%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%

我错过了什么?

6 个答案:

答案 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 +)%|这将完全符合您的要求。