PHP preg_match_all 谜语

PHP preg_match_all riddle

我正在使用 PHP 5.6 版,但我无法弄清楚为什么正则表达式无法正确匹配第二行。

 $str = '<tr><td class="DH">Sale Date</td></tr><tr><td class="DD">10-MAR-15</td></tr><tr><td class="DD">18-APR-17</td></tr>';

 preg_match_all('/<tr>.*?class="D.*?<\/tr>/', $str, $matches);
 print_r($matches);

 preg_match_all('/<tr>.*?class="DH.*?<\/tr>/', $str, $matches);
 print_r($matches);

 preg_match_all('/<tr>.*?class="DD.*?<\/tr>/', $str, $matches);
 print_r($matches);

此代码输出:

Array
(
    [0] => Array
        (
            [0] => <tr><td class="DH">Sale Date</td></tr>
            [1] => <tr><td class="DD">10-MAR-15</td></tr>
            [2] => <tr><td class="DD">18-APR-17</td></tr>
        )

)
Array
(
    [0] => Array
        (
            [0] => <tr><td class="DH">Sale Date</td></tr>
        )

)
Array
(
    [0] => Array
        (
            [0] => <tr><td class="DH">Sale Date</td></tr><tr><td class="DD">10-MAR-15</td></tr>
            [1] => <tr><td class="DD">18-APR-17</td></tr>
        )

)

正则表达式本质上意味着匹配所有最短的序列 <tr></tr> 包含 class="D

注意第一个正则表达式如何分别正确匹配所有 3 行。

第二个做同样的事情,但希望该行包含 class="DH 它正确地做。

第三个正则表达式应该匹配包含 class="DD 的其他行。出于某种原因,只有第一个结果(对应于第二个 table 行)想要包含上一行。

即使我在 </tr><tr> 之间添加 space,就像在 </tr> <tr> 中一样,我也会得到相同的结果。但是,如果我插入一个换行符,事情就会起作用。

任何人都可以解释发生了什么以及如何修复我的代码吗?

/<tr>.*?class="DD.*?/

说“找到 <tr>,然后匹配 所有内容 直到找到 class="DD"。所以它看到:

<tr><td class="DH">Sale Date</td></tr><tr><td class="DD">

并匹配第一个 <tr>,然后 .* 匹配 <td class="DH">Sale Date</td></tr><tr><td,然后它看到匹配下一部分的 class="DH"

当您添加换行符时,.* 停止匹配,因此它可以正常工作。