我需要一个正则表达式,我可以使用PHP的preg_match_all()匹配div-tags内的内容. div看起来像这样:
- <div id="t1">Content</div>
到目前为止,我已经提出了这个正则表达式,它匹配所有id为“t [number]”的div
- /<div id="t(\\d)">(.*?)<\\/div>/
问题是当内容包含更多div时,嵌套的div如下所示:
- <div id="t1">Content <div>more stuff</div></div>
关于如何使我的正则表达式使用嵌套标签的任何想法?
谢谢
解决方法
尝试使用解析器:
- 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解析器更大.此外,正则表达式可能会让你的眼睛流血,你的同事(或维护你的软件的人)可能会在看到你做了什么后来找你.