嵌套Div标签的PHP RegEx

时间:2009-11-12 10:10:04

标签: php regex tags nested

我需要一个正则表达式,我可以使用PHP的preg_match_all()来匹配div-tags中的内容。 div看起来像这样:

<div id="t1">Content</div>

到目前为止,我已经提出了这个正则表达式,它匹配所有div = id [“t [number]”

/<div id="t(\\d)">(.*?)<\\/div>/

问题是当内容包含更多div时,嵌套的div如下:

<div id="t1">Content <div>more stuff</div></div>

关于如何使我的正则表达式使用嵌套标记的任何想法?

由于

4 个答案:

答案 0 :(得分:14)

尝试使用解析器:

require_once "simple_html_dom.php";
$text = 'foo <div id="t1">Content <div>more stuff</div></div> bar <div>even more</div> baz  <div id="t2">yes</div>';
$html = str_get_html($text);
foreach($html->find('div') as $e) {
    if(isset($e->attr['id']) && preg_match('/^t\d++/', $e->attr['id'])) {
        echo $e->outertext . "\n";
    }
}

输出:

<div id="t1">Content <div>more stuff</div></div>
<div id="t2">yes</div>

在此处下载解析器:http://simplehtmldom.sourceforge.net/

编辑:为了我自己的乐趣,我尝试在正则表达式中进行更多操作。这就是我想出的:

$text = 'foo <div id="t1">Content <div>more stuff</div></div> bar <div>even more</div>
      baz <div id="t2">yes <div>aaa<div>bbb<div>ccc</div>bbb</div>aaa</div> </div>';
if(preg_match_all('#<div\s+id="t\d+">[^<>]*(<div[^>]*>(?:[^<>]*|(?1))*</div>)[^<>]*</div>#si', $text, $matches)) {
    print_r($matches[0]);
}

输出:

Array
(
    [0] => <div id="t1">Content <div>more stuff</div></div>
    [1] => <div id="t2">yes <div>aaa<div>bbb<div>ccc</div>bbb</div>aaa</div> </div>
)

一个小小的解释:

<div\s+id="t\d+">  # match an opening 'div' with an id that starts with 't' and some digits
[^<>]*             # match zero or more chars other than '<' and '>'
(                  # open group 1
  <div[^>]*>       #   match an opening 'div'
  (?:              #   open a non-matching group
    [^<>]*         #     match zero or more chars other than '<' and '>'
    |              #     OR
    (?1)           #     recursively match what is defined by group 1
  )*               #   close the non-matching group and repeat it zero or more times
  </div>           #   match a closing 'div'
)                  # close group 1
[^<>]*             # match zero or more chars other than '<' and '>'
</div>             # match a closing 'div'

现在也许你明白为什么人们试图用而不是来说服你使用正则表达式。正如已经指出的那样,如果html的形式不正确,它将无济于事:正如我所向你保证的那样,正则表达式会比html解析器产生更大的混乱。此外,正则表达式可能会让你的眼睛流血,你的同事(或维护你的软件的人)可能会在看到你做了什么后来找你。 :)

最好的办法是先清理输入(使用TIDY或类似内容),然后使用解析器获取所需信息。

答案 1 :(得分:3)

如果你相信这个人,至少有一个正则表达式可以解决这个问题, 他说它比dom方法快...... 我同意他的意见。

http://www.php.net/manual/fr/regexp.reference.recursive.php#95568

$pattern = "/<([\w]+)([^>]*?) (([\s]*\/>)| (>((([^<]*?|<\!\-\-.*?\-\->)| (?R))*)<\/\\1[\s]*>))/xsm";

答案 2 :(得分:1)

我认为最好使用一些DOM-instruments

答案 3 :(得分:1)

正如我最近发现的那样,正则表达式无法做到这一点。

Matching pair tag with regex

我最终使用了xpath,它就像魅力一样