【问题标题】:preg_match_all returns only one matchpreg_match_all 只返回一个匹配项
【发布时间】:2016-02-21 02:30:04
【问题描述】:

我需要一个 php preg_match_all 函数的模式来返回在双花括号内并且在 '

' 和 '' 字符串之间的匹配项。

我尝试创建这样的模式,但它只返回一个匹配项。我预计它会返回“星期一”和“星期二”,但它只返回“星期二”。

这是模式

/<body>(.)*{{(?<DAY>.*?)}}(.)*<\/body>/s

这是用于测试的字符串:

<body>
s{s ds
ds{{Monday}}ds
s
dsd}{s
ds{{Tuesday}}dsd sdsd
d{}sd}s


}
{
fdsa dsafasd
</body>

谢谢

【问题讨论】:

    标签: php regex preg-match-all


    【解决方案1】:

    它只返回一个匹配项的原因是因为您从 &lt;body&gt; 元素的开头匹配到 &lt;/body&gt; 元素的结束,只有一个捕获组。

    要解决此问题,您可以使用\G anchor 以便在上一个匹配结束时继续匹配:

    /<body>|(?!^)\G(.*?){{(?<DAY>.*?)}}(?=.*<\/body>)/s
    

    Live Example:

    preg_match_all("/<body>|(?!^)\G(.*?){{(?<DAY>.*?)}}(?=.*<\/body>)/s", $input, $matches, PREG_SET_ORDER);
    
    foreach ($matches as $match) {
        if (isset($match['DAY'])) {
            echo $match['DAY'];
        }
    }
    

    根据您提供的输入输出:

    周一周二


    值得指出的是,如果您知道每个匹配项都在 &lt;body&gt; 元素内,您可以简单地使用:

    preg_match_all("/{{(?<DAY>.*?)}}/", $input, $matches, PREG_SET_ORDER);
    

    【讨论】:

    • 不,匹配将在正文标签之间和正文之外。例如。在网页代码的头部。感谢您的工作模式。关于这部分的一个问题:“(?!^)”。这是否意味着任何不跟在测试字符串开头的东西?
    • @trzczy \G 锚将在前一个匹配的末尾继续匹配它将从字符串的开头开始匹配。负前瞻 (?!^) 只是阻止它在开头匹配,因此匹配始终以 &lt;body&gt; 开头,\G 始终从那里继续。如果 &lt;head&gt; 元素内有匹配项,它似乎在 this example 中有效。
    • 乔希,非常非常非常感谢您的大力帮助!
    【解决方案2】:

    我认为更简单的方法是在第一步中获取正文标签之间的文本。使用第二个正则表达式,您可以检索花括号中的元素

    /({{(Monday|Tuesday)}})+/s
    

    【讨论】:

      猜你喜欢
      • 2014-12-26
      • 2015-03-14
      • 2014-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 2014-04-08
      • 1970-01-01
      相关资源
      最近更新 更多