【问题标题】:PHP RegExp for nested Div tags用于嵌套 Div 标签的 PHP RegEx
【发布时间】:2023-09-02 06:58:01
【问题描述】:

我需要一个可以与 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>

关于如何使我的正则表达式与嵌套标签一起工作的任何想法?

谢谢

【问题讨论】:

    标签: php regex tags nested


    【解决方案1】:

    我认为使用一些DOM-instruments会更好

    【讨论】:

    • 谢谢,但我的文档包含错误,使用正则表达式会更容易
    • +1。如果它包含错误,则使用正则表达式会更加困难。
    【解决方案2】:

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

    Matching pair tag with regex

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

    【讨论】:

    • 感谢您的回答,我不使用 XPATH/DOM 解析的原因是文档包含错误。我找到了这个正则表达式:''#
      ]*>(?:(?:(?!?div).)*|(?R))*
      #si'。但我无法根据自己的需要进行调整。
    • 您在面对多个告诉您“不”的答案时的坚持值得称赞,但您真的无法使用正则表达式解析 HTML
    【解决方案3】:

    改用解析器:

    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 或类似方法),然后使用解析器获取您想要的信息。

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        最近更新 更多