【问题标题】:Regex to match string between %正则表达式匹配 % 之间的字符串
【发布时间】:2010-11-19 05:34:46
【问题描述】:

我正在尝试匹配包含在 % 中的子字符串,但 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%

我错过了什么?

【问题讨论】:

    标签: php regex preg-match-all


    【解决方案1】:

    将正则表达式中的“.”替换为“[^%]”:

    preg_match_all("/%[^%]*%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches);
    

    正在发生的事情是“.”是“贪婪地”尽可能多地匹配,包括直到最后 % 的所有内容。用否定字符类“[^%]”替换它意味着它将匹配任何除了百分比,这将使它只匹配你想要的位。

    另一种选择是在点之后放置一个“?”,告诉它“不要贪婪”:

    preg_match_all("/%.*?%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches);
    

    在上面的示例中,任何一个选项都可以,但是有时您可能会搜索大于单个字符的内容,因此否定字符类将无济于事,因此解决方案是取消匹配匹配。

    【讨论】:

      【解决方案2】:

      你正在做一个贪婪的匹配 - 使用 ? 让它变得不贪婪:

      /%.*?%/
      

      如果匹配中可以出现换行符,请添加 s (DOTALL) 修饰符:

      /%.*?%/s
      

      【讨论】:

        【解决方案3】:

        添加一个? * 之后:

        preg_match_all("/%.*?%/", "%hey%_thereyou're_a%rockstar%\nyo%there%", $matches);
        

        【讨论】:

          【解决方案4】:

          原因是星星很贪心。也就是说,星号使正则表达式引擎尽可能频繁地重复前面的标记。你应该试试 。*?而是。

          【讨论】:

            【解决方案5】:

            您可以尝试/%[^%]+%/ - 这意味着在百分号之间您只想匹配不是百分号的字符。

            您也可以使模式不贪婪,例如/%.+%/U,所以它会尽可能少地捕获(我认为)。

            【讨论】:

            【解决方案6】:

            |%(\w+)%|这将完全符合您的要求。

            【讨论】:

              【解决方案7】:

              虽然解决方案是将贪婪的.* 变成懒惰的.*?(或将.* 替换为[^%]*),但您可能还想真正摆脱输出中的% 符号。

              在这种情况下,如果发生匹配,您将需要使用捕获组并获取 $matches[1]

              $str = "%hey%_thereyou're_a%rockstar%\nyo%there%";
              if (preg_match_all("/%([^%]*)%/", $str, $matches)) {
                  print_r($matches[1]);
              }
              // => Array( [0] => hey [1] => rockstar [2] => there )
              

              请注意,print_r($matches[0]); 将输出完整匹配,// => Array( [0] => %hey% [1] => %rockstar% [2] => %there% )[^%] 模式是一个否定字符类,它匹配除 % 字符之外的任何字符。

              the PHP demo

              变体

              如果您需要确保% 字符之间只有字母、数字或下划线,可以使用

              "/%(\w*)%/"
              

              如果您想匹配除% 和两个% 字符之间的空格以外的任何字符,请使用

              "/%([^\s%]*)%/"
              

              [^\s%]* 模式是一个正则表达式,它匹配除空格 (\s) 和 % 字符之外的任何零个或多个字符。

              【讨论】:

                猜你喜欢
                • 2020-10-19
                • 1970-01-01
                • 1970-01-01
                • 2012-09-26
                • 1970-01-01
                • 2022-09-23
                • 2016-09-02
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多