php和preg_match:如何在多行html中捕获数据?

时间:2014-09-06 15:43:54

标签: php regex

目标是夺取巴黎 包含在

之间
<th>City :</th><td>(.)*</td>

这是我的来源

                <tr>
                    <th>postal code :</th>
                    <td>75012</td>
                </tr>

                <tr>
                    <th>City :</th>
                    <td>Paris</td>
                </tr>

我试过

/<th>City :</th><td>(.)*</td>/gmi

表达没有运气。有什么想法吗?

3 个答案:

答案 0 :(得分:2)

你在这里遇到一些问题。

  1. PHP不支持g(全局)修饰符,而m(多行)修饰符会导致^$匹配开始/每行结束。你可以删除它们,我们不需要它们。

  2. 您需要考虑thtd元素之间的空白。

  3. 您正在重复捕获组(.)*,因此只捕获最后一次迭代,在这种情况下,将捕获巴黎的s字母,而不是td的全部内容。 1}}元素。

  4. 对于这个简单的案例,以下就足够了:

    ~<th>City :</th>\s*<td>(.*?)</td>~i
    

    注意: *运算符跟随点.说匹配任何字符,除了换行“零或更多”次。在操作员*?之后提供问号时,您告诉引擎返回非greedy匹配。

    但是,为了在不久的将来解析HTML,我建议使用DOM等工具。

    $dom = DOMDocument::loadHTML('
         <tr>
          <th>postal code :</th>
          <td>75012</td>
         </tr>
         <tr>
          <th>City :</th>
          <td>Paris</td>
         </tr>
    ');
    $xp = new DOMXPath($dom);
    $td = $xp->query('//th[contains(.,"City")]/following-sibling::*[1]');
    echo $td->item(0)->nodeValue; //=> "Paris"
    

答案 1 :(得分:1)

您只需要启用dotall修饰符并将.*?置于</th><td>标记之间,以便它与现有的换行符匹配。此外,您还需要将*置于捕获组内,否则它将捕获字符串Paris中的最后一个字符

<th>City :</th>.*?<td>(.*?)</td>

DEMO

答案 2 :(得分:0)

可能更慢但更容易广泛使用:http://php.net/manual/en/class.domelement.php