正则表达式中的多重匹配

时间:2016-06-24 16:07:26

标签: regex pcre regex-lookarounds

图案和文字在线显示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 ->;:4abc

但只找到第一个。

如何获得这个? 谢谢。

3 个答案:

答案 0 :(得分:0)

正则表达式从来都不是解析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
)

答案 1 :(得分:0)

虽然我同意反对使用Regex for HTML的观点,但回答你的问题,消除(?<=<code>)背后的外观也允许Regex找到第二次出现。这留下了以下正则表达式:

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

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

答案 2 :(得分:0)

一种方法是首先使用/<code[^>]*?>(.*?)<\/code>/gs/<span[^>]*?>(.*?)<\/span>/gs这些匹配来获取代码块。

如果遇到问题,这些“更简单”的正则表达式也可以使调试更容易。此外,它还可以按顺序从多个代码块中提取所有跨度。