为什么不(。*?)获取preg_match_all中的html标记之间的所有内容?

时间:2017-09-07 12:54:50

标签: regex preg-match

我似乎无法理解为什么四小时后我无法获得两个标签之间的所有数据,其中3个是返回但是第4个不是(35滴li)。

$ string = '<ul>
    <li>
    <strong>½ cup</strong>&nbsp;white wine </li>
    <li>
    <strong>½ cup</strong>&nbsp;extra virgin olive oil</li>
    <li>
    <strong>35 drops</strong> of water
    </li>
    <li>
    <strong>½ cup</strong>&nbsp;golden flaky raspberries</li>
    </ul>
';

preg_match_all("/<li>\n<strong>(.*?)<\/strong>(.*?)<\/li>/", $string, $matched);

这是我得到的结果:

0   =>  array(3
        0   =>  <li>
                <strong>½ cup</strong>&nbsp;white wine vinegar</li>
        1   =>  <li>
                <strong>½ cup</strong>&nbsp;extra virgin olive oil</li>
        2   =>  <li>
                <strong>½ cup</strong>&nbsp;golden raspberries</li>
        )   
1   =>  array(3
        0   =>  ½ cup
        1   =>  ½ cup
        2   =>  ½ cup
        )
2   =>  array(3
        0   =>  &nbsp;white wine vinegar
        1   =>  &nbsp;extra virgin olive oil
        2   =>  &nbsp;golden raspberries
        )
)

我正在尝试检索的是强标签内的所有内容,而强标签之外的所有内容都在数组1和2中。

http://www.phpliveregex.com/p/lf8

2 个答案:

答案 0 :(得分:1)

35滴的结束标记在新行上,你的正则表达式缺少新行:

<li>\n<strong>(.*?)<\/strong>(.*?)\n?<\/li>
                                  ^^^

稍微好一点的是使用否定的字符类(如果需要,可以匹配换行符):[^<]

<li>\n<strong>([^<]*)<\/strong>([^<]*)<\/li>

regex101 demo

更好的方法是使用html解析器。

答案 1 :(得分:0)

首先,不要将正则表达式用于HTML或XML。还有其他工具。我不熟悉PHP生态系统,但谷歌给了我PHP simple HTML DOM Parser。也许它值得一试。

然后,如果你真的想用正则表达式做,那么你需要对你的文本进行假设。例如。属性是在撇号或引号内?你期望这些属性以什么顺序?你能容忍多少/什么样的空白?等

在您的情况下,您假设结束</li>与文本位于同一行。但是,对于第3个<li>,它不是真的。它包含一个换行符。您可以通过添加它来修复正则表达式:((.|\n)*?)<\/li>