正则表达式找到target =“_ blank”链接并在关闭标记之前添加文本

时间:2013-04-23 18:46:48

标签: php regex hyperlink

我需要能够解析一些文本并查找标记具有target =" _blank" ....的所有实例,并且对于每个匹配,添加(例如):此链接打开关闭标签前的新窗口。

例如:

在:

<a href="http://any-website-on-the-internet-or-local-path" target="_blank">Go here now</a>

后:

<a href="http://any-website-on-the-internet-or-local-path" target="_blank">Go here now<span>(This link opens in a new window)</span></a>

这是一个PHP站点,所以我假设preg_replace()将是方法...我只是没有正确编写正则表达式的技能。

提前感谢任何人提供的任何帮助。

5 个答案:

答案 0 :(得分:7)

你永远不应该使用正则表达式来解析HTML,除非是在非常明确和受控制的情况下。

相反,请尝试使用内置解析器:

$dom = new DOMDocument();
$dom->loadHTML($your_html_source);
$xpath = new DOMXPath($dom);
$links = $xpath->query("//a[@target='_blank']");
foreach($links as $link) {
    $link->appendChild($dom->createTextNode(" (This link opens in a new window)"));
}
$output = $dom->saveHTML();

或者,如果将其输出到浏览器,则可以使用CSS:

a[target='_blank']:after {
    content: ' (This link opens in a new window)';
}

答案 1 :(得分:1)

这适用于替换锚标签....

$string = str_replace('<a ','<a target="_blank" ',$string);

答案 2 :(得分:0)

嗯@Kolink是对的,但是我的RegExp版本。

$string = '<p>mess</p><a href="http://google.com.br/" target="blank" class=\"bother\">Google</a><p>mess</p>';
echo preg_replace("/(\<a.*?target=\"blank\".*?>)(.*?)(\<\/a\>)/miU","$1$2(This link opens in a new window)$3",$string);

答案 3 :(得分:-1)

这就是工作:

$newText = '<span>(This link opens in a new window)</span>';
$pattern = '~<a\s[^>]*?\btarget\s*=(?:\s*([\'"])_blank\1|_blank\b)[^>]*>[^<]*(?:<(?!/a>)[^<]*)*\K~i';
echo preg_replace($pattern, $newText, $html);

然而,这种直接字符串方法可能会替换css或javascript代码中注释的html部分,字符串或注释,并最终取代javascript文字正则表达式,这最多是不需要的,最糟糕的是根本不需要。这就是为什么你应该使用DOM方法,如果你想避免这些陷阱。您所要做的就是为每个具有所需属性的链接附加一个新节点:

$dom = new DOMDocument;
libxml_use_internal_errors(true);
$dom->loadHTML($html);
$xp = new DOMXPath($dom);
$nodeList = $xp->query('//a[@target="_blank"]');

foreach($nodeList as $node) {
    $newNode = dom->createElement('span', '(This link opens in a new window)');
    $node->appendChild($newNode);
}

$html = $dom->saveHTML();

要完成,最后一个选择包括不更改html并使用css:

a[target="_blank"]::after {
    content: " (This link opens in a new window)";
    font-style: italic;
    color: red;
}

答案 4 :(得分:-2)

您将无法编写将评估无限长字符串的正则表达式。我建议:

$h = explode('>', $html);

这将使您有机会像任何其他数组一样遍历它,然后执行:

foreach($h as $k){
    if(!preg_match('/^<a href=/', $k){
        continue;
        }elseif(!preg_match(/target="_blank")/, $k){
        continue;
        }else{
        $h[$k + 1] .= '(open in new window);
        }
    }
$html = implode('>', $h);

这就是我如何解决这个问题。当然,我只是把它扔出了我的头顶并注意保证按原样工作,但是对你的确切逻辑进行一些可能的调整,你就会得到你需要的东西。