PHP正则表达式从非捕获组中提取内部内容

时间:2012-08-02 13:37:51

标签: php regex performance

我正在从一个很长的HTML表中解析信息;现在我正在使用的代码使用DOMDocument,DOMElement(etc)类进行解析。我想做一个性能测试来运行当前的方法来对抗Regex从表中获取信息,但我无法得到正确的表达式。

表格的HTML行如下所示:

<tr><td>   JON SMITH     </td><td> 2000-09-29 </td></tr>

我一直在尝试的表达看起来像这样:

/(?:<td>([a-zA-Z\s]*?)<\/td><td>([0-9-\s]*?)<\/td>)/

上述表达式的问题在于它返回整个行内容而不仅仅是内部列内容。理想情况下,preg_match_all数组结果将是名称,日期,名称,日期等。

这是合理的做法,还是应该坚持使用DOM技术?如果它是合理的,有人可以借助正则表达式吗?

谢谢!

编辑:如果将来有人发现这种情况,RegEx解决方案的性能比使用DOM类更好;在我的情况下,这是秒与分钟之间的差异。

2 个答案:

答案 0 :(得分:0)

我的解决方案:

步骤1。搜索<table>...</table>
/<table[^>]*+>([^<]*+(?:(?!<\/?+table)<[^<]*+)*+)<\/table>/i

步骤2。从step1 group1搜索所有<tr>...</tr>
/<tr[^>]*+>([^<]*+(?:(?!<\/?+tr)<[^<]*+)*+)<\/tr>/ix

步骤3。从每个<td>...</td>中提取数据(来自step2 group1):
/<td[^>]*+>([^<]*+(?:(?!<\/?+td)<[^<]*+)*+)<\/td>/ix

这些可怕的模式指的是Mastering Regular Expressions 3rd

示例代码:

    <?php
$foo = '<tr><td>   JON SMITH     </td><td> 2000-09-29 </td></tr>';
if(preg_match_all('/<td[^>]*+>([^<]*+(?:(?!<\/?+td)<[^<]*+)*+)<\/td>/ix', $foo, $matches) > 0){
    for($i = 0; $i < count($matches[0]); ++$i)
        printf("%s\n", $matches[0][$i]);

    for($i = 0; $i < count($matches[1]); ++$i)
        printf("%s\n", $matches[1][$i]);
}
?>

输出:

<td>   JON SMITH     </td>
<td> 2000-09-29 </td>
JON SMITH
2000-09-29

答案 1 :(得分:0)

使用preg_match_all()并传递第三个参数和数组以填充第四个参数PREG_SET_ORDER。

preg_match_all("/(?:<td>([a-zA-Z\s]*?)<\/td><td>([0-9-\s]*?)<\/td>)/", $html, $matches, PREG_SET_ORDER);

结果数组应如下所示:

$matches => array(
   [0] => array(
      [0] => '<td>   JON SMITH     </td><td> 2000-09-29 </td>',
      [1] => '   JON SMITH     ',
      [2] => ' 2000-09-29 '
   ),
   [1] => array(
      [0] => '<td>   JACK BOLD     </td><td> 2000-10-20 </td>',
      [1] => '   JACK BOLD     ',
      [2] => ' 2000-10-20 '
   ),
   ...
);

请参阅preg_match_all() documentation.