【问题标题】:Find multiple patterns with a single preg_match_all in PHP在 PHP 中使用单个 preg_match_all 查找多个模式
【发布时间】:2011-05-30 23:27:59
【问题描述】:

使用 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>

【问题讨论】:

  • @mario:实际上两者兼而有之,只是有点夸张。重要的一点是:“正则表达式是一种不够复杂的工具,无法理解 HTML 使用的结构。HTML 不是正则语言,因此不能被正则表达式解析。”
  • 你应该use an XML parser.(继续,也标记这条评论)
  • 不要使用正则表达式解析 HTML。使用适当的 HTML 解析模块。 您无法使用正则表达式可靠地解析 HTML,并且您将面临悲伤和挫败感。一旦 HTML 与您的期望发生变化,您的代码就会被破坏。有关如何使用已经编写、测试和调试的 PHP 模块正确解析 HTML 的示例,请参阅 htmlparsing.com/php

标签: php regex


【解决方案1】:

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

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

综合起来:

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

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

【讨论】:

    【解决方案2】:

    这个对我有用

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

    【讨论】:

      【解决方案3】:

      如果您要使用 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);
      

      【讨论】:

        【解决方案4】:

        虽然doable 使用正则表达式,但您可以使用更简单的 HTML 解析器工具包之一来简化任务。例如,使用 phpQuery 或 QueryPath 很简单:

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

        【讨论】:

          猜你喜欢
          • 2013-05-01
          • 2014-06-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多