我遇到以下问题,我有这样的结构:
$table = '
<table>
<tbody>
<tr valign="top">
<td>foo</td>
<td>bar</td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr valign="top">
<td>bee</td>
<td>dog</td>
</tr>
</tbody>
</table>';
我正在尝试检索一个包含所有<tr>
的数组,但没有成功。我能做到的最接近的模式,让所有人都搞砸了。
$pattern = "/<tr valign[^>]*>(.*)<\/tr>/s";
preg_match_all($pattern, $table, $matches, PREG_PATTERN_ORDER);
如果我放var_dump($matches)
,我想要一个返回的数组:
array(
[0] => "<td>foo</td><td>bar</td>",
[1] => "<td>bee</td><td>dog</td>"
);
......或接近它的东西。
但我收到了:
string(301) "
foo
bar
"
<table>
<tbody>
<tr valign="top">
<td>bee</td>
<td>dog</td>
</tr>
</tbody></table>
任何人都知道我做错了什么?
提前致谢。
答案 0 :(得分:7)
你必须使你的量词变得懒惰:.*
=&gt; .*?
当您使用贪心量词时,.*
将使用所有可能的字符,当您使用延迟量词时,.*?
将占用最少的字符数。
当你使用延迟量词时,正则表达式引擎将逐个取字符并测试每个字符的模式完成。
当你使用贪婪量词(默认行为)时,正则表达式引擎将采用所有可能的字符(直到你的情况结束),并逐个字符地回溯,直到模式完成成功。
注意:
添加PREG_PATTERN_ORDER
是没用的,因为它是preg_match_all
的默认设置。
DOMDocument可能是一个更适合处理html的工具。例如:
$dom = new DOMDocument();
@$dom->loadHTML($table);
$trs = $dom->getElementsByTagName('tr');
$results = array();
foreach ($trs as $tr) {
if ($tr->hasAttribute('valign')) {
$children = $tr->childNodes;
$tmp = '';
foreach ($children as $child) {
$tmp .= trim($dom->saveHTML($child));
}
if (!empty($tmp)) $results[] = $tmp;
}
}
echo htmlspecialchars(print_r($results, true));