在PHP中使用单个preg_match_all查找多个模式

时间:2010-12-27 00:28:15

标签: php regex

使用PHP和preg_match_all我正在尝试获取以下标记之间的所有HTML内容(以及标记):

<p>paragraph text</p>
don't take this
<ul><li>item 1</li><li>item 2</li></ul>
don't take this
<table><tr><td>table content</td></tr></table>

我可以得到其中一个就好了:

preg_match_all("(<p>(.*)</p>)siU", $content, $matches, PREG_SET_ORDER);

有没有办法获得所有

<p></p> <ul></ul> <table></table>

内容只有一个preg_match_all?我需要它们按照它们被发现的顺序出来,这样我才能回应内容,这将是有意义的。

所以如果我在上面的内容上做了一个preg_match_all,那么迭代通过$ matches数组就会回显:

<p>paragraph text</p>
<ul><li>item 1</li><li>item 2</li></ul>
<table><tr><td>table content</td></tr></table>

4 个答案:

答案 0 :(得分:10)

使用|匹配一组字符串中的一个:p|ul|table

使用反向引用来匹配适当的结束标记:\\2,因为组(pl|ul|table)包含第二个左括号

把所有这些放在一起:

preg_match_all("(<(p|ul|table)>(.*)</\\2>)siU", $content, $matches, PREG_SET_ORDER);

如果您的输入html遵循非常严格的结构,这只会起作用。它不能在标记中包含空格,也不能在标记中包含任何属性。当有任何嵌套时它也会失败。考虑使用html解析器来做正确的工作。

答案 1 :(得分:4)

这个对我有用

preg_match_all("#<\b(p|ul|table)\b[^>]*>(.*?)</\b(p|ul|table)\b>#si", $content, $matches)

答案 2 :(得分:1)

如果你要使用DOM解析器,那么你应该这样做。贡献者发布了useful function for obtaining a DOMNode's innerHTML,我将在以下示例中使用:

$dom = new DOMDocument;
$dom->loadHTML($html);

$p = $dom->getElementsByTagName('p')->item(0); // first <p> node
$ul = $dom->getElementsByTagName('ul')->item(0); // first <ul> node
$table = $dom->getElementsByTagName('table')->item(0); // first <table> node

echo DOMinnerHTML($p);
echo DOMinnerHTML($ul);
echo DOMinnerHTML($table);

答案 3 :(得分:0)

doable使用正则表达式时,您可以使用一个更简单的HTML解析器工具包来简化任务。例如,使用phpQuery或QueryPath,它就像:

一样简单
qp($html)->find("p, ul, table")->text();   // or loop over them