【问题标题】:PHP Preg Matching Capture Groups [duplicate]PHP Preg匹配捕获组[重复]
【发布时间】:2013-04-18 19:46:30
【问题描述】:

我似乎无法掌握 php 中的正则表达式。具体来说就是群抓部分。

我有一个看起来像这样的字符串

<table cellpadding="0" cellspacing="0" border="0" width="100%" class="List">

  <tr class='row_type_1'>
    <td class="time">
                      3:45 pm
    </td>
    <td class="name">
                      Kira
    </td>
  </tr>

  <tr class='row_type_2'>
    <td class="time">
                      4:00 pm
    </td>
    <td class="name">
                      Near
    </td>
  </tr>

</table>

我希望我的数组看起来像这样

Array
(
   [0] => Array
   (
      [0] => 3:45 pm
      [1] => Kira
   )
   [1] => Array
   (
      [0] => 4:00 pm
      [1] => Near
   )
)

我只想使用 preg_match,而不是explode,array_keys 或循环。我花了一段时间才发现我需要一个 /s 来表示 .* 来计算换行符;我真的很想看看这个模式和捕获语法。

编辑:该模式只需要 (row_type_1|row_type_2) 之类的东西来捕获我想要从中获取数据的表中仅有的两种类型的行。例如,在 row_type_2 之后是 row_type_3,然后是 row_type_1,然后 row_type_3 将被忽略,数组只会添加来自 row_type_1 的数据,如下所示。

Array
(
   [0] => Array
   (
      [0] => 3:45 pm
      [1] => Kira
   )
   [1] => Array
   (
      [0] => 4:00 pm
      [1] => Near
   )
   [2] => Array
   (
      [0] => 5:00 pm
      [1] => L
   )
)

【问题讨论】:

  • 永远不要使用正则表达式处理 HTML,而是使用 DOM 解析器。
  • 您能说出原因吗?
  • @SatbirKira:因为你不会做对。并且对您的标记进行最轻微的更改,您的正则表达式就会被破坏。使用 HTML 解析器。
  • 你是绝对正确的。谢谢。

标签: php html regex multidimensional-array preg-match


【解决方案1】:

我会使用 XPath 和 DOM 从 HTML 中检索信息。如果 HTML 或查询变得更复杂,为此使用正则表达式可能会变得混乱。 (如您目前所见)。 DOM 和 XPath 是这方面的标准。为什么不使用它?

想象一下这个代码示例:

// load the HTML into a DOM tree
$doc = new DOMDocument();
$doc->loadHtml($html);

// create XPath selector
$selector  = new DOMXPath($doc);

// grab results
$result = array();
// select all tr that class starts with 'row_type_'
foreach($selector->query('//tr[starts-with(@class, "row_type_")]') as $tr) {
    $record = array();
    // select the value of the inner td nodes
    foreach($selector->query('td[@class="time"]', $tr) as $td) {
        $record[0]= trim($td->nodeValue);
    }
    foreach($selector->query('td[@class="name"]', $tr) as $td) {
        $record[1]= trim($td->nodeValue);
    }
    $result []= $record;
}

var_dump($result);

【讨论】:

  • 感谢您带领我朝着正确的方向前进。我将尝试使用一个名为“PHP Simple HTML DOM Parser”的库。
  • 如果你喜欢,你可以做到。为此目的,它比正则表达式要好得多。 :) 我更喜欢 DOMXPath 作为它的内置 php,因此它将是 1.) 开箱即用 2.) 更快
  • 如果我正在抓取的网站更改了它的 html,我不能说 DOMXPath 看起来我会很乐意回去修复。我拥有自己的服务器空间,所以我可以使用外部库。有趣的是,我在大学的 c++/bash/shell 课程中的第一个项目是使用 egrep 废弃他们的网站。显然,我应该知道这是不切实际的,只是为了举例。
  • 你可以告诉他们关于 DOM 的事。也许你会得到一些额外的分数;)
  • 一年前上过这门课。干杯。
【解决方案2】:

你不应该使用正则表达式来解析 html 有几个原因。最大的原因是很难解释格式不正确的 html 并且尝试变得又大又慢。

我建议考虑使用 php DOM 解析器或 php HTML 解析器。

【讨论】:

    【解决方案3】:

    试试这个:

    function extractData($str){
        preg_match_all("~<tr class='row_type_\d'>\s*<td class=\"time\">(.*)</td>\s*<td class=\"name\">(.*)</td>\s*</tr>~Usim", $str, $match);
        $dataset = array();
        array_shift($match);
        foreach($match as $rowIndex => $rows){
            foreach ($rows as $index => $data) {
                $dataset[$index][$rowIndex] = trim($data);
            }
        }
        return $dataset;
    }
    
    $myData = extractData($str);
    

    【讨论】:

      【解决方案4】:

      地狱之路就在这里:

      $pattern = '`<tr .*?"time">\s++(.+?)\s++</td>.*?"name">\s++(.+?)\s++</td>`s';
      preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);
      foreach ($matches as &$match) {
          array_shift($match);
      }
      ?><pre><?php print_r($matches);
      

      【讨论】:

        猜你喜欢
        • 2021-06-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-17
        • 1970-01-01
        相关资源
        最近更新 更多