【问题标题】:multiple match in regex正则表达式中的多重匹配
【发布时间】:2016-06-24 16:07:26
【问题描述】:

图案和文字在线展示https://regex101.com/r/aL5dD4/2 该模式应该找到位于代码标签之间的 span 元素的节点值。

正文如下:

<code>
    <div>
        <span ds = 'dsds'>12 3 ->;:4</span><span>abc</span>
    </div>
</code>

正则表达式模式如下:

/(?<=<code>).*?<span[^>]*?>(.*?)(?=<\/span>.*?<\/code)/gs

我需要它来匹配两个节点值 12 3 -&gt;;:4abc

但只找到第一个。

如何获得? 谢谢。

【问题讨论】:

标签: regex pcre regex-lookarounds


【解决方案1】:

Regex 从来都不是解析 HTML/XML 的好工具。如下使用DOM

$html=<<<EOF
<code>
    <div>
        <span ds = 'dsds'>12 3 ->;:4</span><span>abc</span>
    </div>
</code>
EOF;

$xpath = new DOMXPath(@DOMDocument::loadHTML($html));    
$nodeList = $xpath->query('//code/div/span');

$vals = array();
for($i=0; $i < $nodeList->length; $i++) {
    $vals[] = $nodeList->item($i)->nodeValue;
}

print_r( $vals );

Code Demo

输出:

Array
(
    [0] => 12 3 ->;:4
    [1] => abc
)

【讨论】:

    【解决方案2】:

    虽然我同意反对将 Regex 用于 HTML 的观点,但为了回答您的问题,消除 (?&lt;=&lt;code&gt;) 背后的外观允许 Regex 也可以找到第二个匹配项。这留下了以下正则表达式:

    <span[^>]*?>(.*?)(?=<\/span>.*?<\/code)
    

    注意:这会返回两个单独的匹配项,并且不需要在元素中找到字符串。要要求匹配位于代码块中,您可以使用 @HamZa 的注释解决方案(尽管此解决方案提供 1 个匹配两个组作为字符串),它甚至可能更接近您正在寻找的内容。

    【讨论】:

      【解决方案3】:

      一种方法是首先使用/&lt;code[^&gt;]*?&gt;(.*?)&lt;\/code&gt;/gs 之类的内容获取代码块,然后在这些匹配项上使用/&lt;span[^&gt;]*?&gt;(.*?)&lt;\/span&gt;/gs

      这些“更简单”的正则表达式还可以让您在遇到问题时更轻松地进行调试。此外,这种方法从多个代码块中顺序提取所有跨度。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-09-10
        • 1970-01-01
        • 1970-01-01
        • 2014-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多