在特定字符串之后使用preg_match查找模式的所有连续出现


Finding all consecutive occurences of a pattern using preg_match after a specific string

我有一个巨大的html文档,其中包含具有唯一表ID的不同表。类似于:

<table class="my_table" id="table_id1">
  <tr class="odd"><td>Line 1</td></tr>
  <tr class="even"><td>Line 2</td></tr>
  <tr class="odd"><td>Line 3</td></tr>
  <tr class="even"><td>Line 4</td></tr>
</table>
<table class="my_table" id="table_id2">
  <tr class="odd"><td>Line 1</td></tr>
  <tr class="even"><td>Line 2</td></tr>
  <tr class="odd"><td>Line 3</td></tr>
</table>

是否可以使用preg_match查找特定表的所有行的HTML?

我尝试了以下代码:

preg_match('/<table[^>]*id="table_id2">(<tr[^>]*><td>[^>]*<'/td><'/tr>)+/', $html, $matches); 
//$html variable contains the html.

但它返回的输出类似于:

Array
(
    [0] => Array
        (
            [0] => <table class="my_table" id="table_id2"><tr class="odd"><td>Line 1</td></tr><tr class="even"><td>Line 2</td></tr><tr class="odd"><td>Line 3</td></tr>
        )
    [1] => Array
        (
            [0] => <tr class="odd"><td>Line 3</td></tr>
        )
)

但我需要这样的输出:

Array
(
    [0] => Array
        (
            [0] => <table class="my_table" id="table_id2"><tr class="odd"><td>Line 1</td></tr><tr class="even"><td>Line 2</td></tr><tr class="odd"><td>Line 3</td></tr>
        )
    [1] => Array
        (
            [0] => <tr class="odd"><td>Line 1</td></tr>
            [1] => <tr class="odd"><td>Line 2</td></tr>
            [2] => <tr class="odd"><td>Line 3</td></tr>
        )
)

有可能吗?请帮忙。

您不应该使用regex来解析HTML。PHP有一个很好的工具——DOMDocument。使用它,您可以做很多事情,使用regex是不可能/几乎不可能的。您的样品将看起来像:

$sHtml = '<table class="my_table" id="table_id1">
  <tr class="odd"><td>Line 1</td></tr>
  <tr class="even"><td>Line 2</td></tr>
  <tr class="odd"><td>Line 3</td></tr>
  <tr class="even"><td>Line 4</td></tr>
</table>
<table class="my_table" id="table_id2">
  <tr class="odd"><td>Line 1</td></tr>
  <tr class="even"><td>Line 2</td></tr>
  <tr class="odd"><td>Line 3</td></tr>
</table>';
$rDoc   = new DOMDocument();
$rDoc->loadHTML($sHtml);
$sId    = 'table_id2';
//found table:
$rTable = $rDoc->getElementById($sId);
foreach($rTable->childNodes as $rItem)
{
   //do something with item:
   //var_dump($rItem);
}

试试这个。它与您所拥有的非常相似,但我在每行周围放置了一个非捕获分组,并在每行中放置了一些前导和尾随的可选空白。

作为参考,使用的正则表达式是

/<table[^>]*id="table_id2">((?:'s*<tr[^>]*><td>[^>]*<'/td><'/tr>'s*)+)/