如果您希望秘密保密,如何删除<a> tags that contain hashtags in their text?

时间:2018-01-22 10:52:45

标签: php html regex preg-replace hashtag

I want to delete the linked hashtags

I do not want to delete hashtags without links.

I do not want to delete other links.

For example:

<p><a href="/user/username" >Username</a> #filmphotography #vintage <a href="/tag/travelgram" >#travelgram</a> #montreux #royalpalacehotel <a href="/tag/switzerland">#switzerland</a> #selfie <a href="/tag/meandmysister">#meandmysister</a></p>

I want to be:

<p><a href="/user/username" >Username</a> #filmphotography #vintage  #montreux #royalpalacehotel #selfie </p>

This code doesn't work:

$html = preg_replace('#<a(.*?)>#(.*?)</a>#is', '', $html);

2 个答案:

答案 0 :(得分:1)

使用字符集代替量词的简短回答

 <a[^>]*>#[^<#]*<\/a>

regex101

它更有效率,因为无法回溯,并避免回溯不需要的结果。

(.*?)懒惰量词意味着最短的匹配但是在回溯的情况下它会包含更大的匹配,因为起得太早。

如果出现意外匹配,可以改进正则表达式。

答案 1 :(得分:1)

正如rollstuhlfahrer所指出的那样,你已经使用了一个非转义字符,也就是模式分隔符。解决此问题的最简单方法是将分隔符更改为模式本身未使用的有效分隔符(例如~)。

您的新模式如下所示:~<a(.*?)>#(.*?)</a>~is

但还有更多坏消息......

您的输出将是:

<p> #montreux #royalpalacehotel  #selfie </p>

正则表达式引擎试图让你开心,并尽力为你找到匹配。在这样做的过程中,它会不断扩展搜索范围,超出预期的限定标签,并且还会吞噬不合格的标签!

这是个好消息:获胜的DomDocument!

代码:(Demo

$html='<p><a href="/user/username" >Username</a> #filmphotography #vintage <a href="/tag/travelgram" >#travelgram</a> #montreux #royalpalacehotel <a href="/tag/switzerland">#switzerland</a> #selfie <a href="/tag/meandmysister">#meandmysister</a></p>';
$dom = new DOMDocument;
$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); // 2nd params to remove DOCTYPE);
foreach($dom->getElementsByTagName('a') as $a){
    if(strpos($a->nodeValue,'#')===0){
        $remove[]=$a;
    }
} 
foreach($remove as $bad_a){
    $bad_a->parentNode->removeChild($bad_a); 
}     
echo $dom->saveHTML();

输出:

<p><a href="/user/username">Username</a> #filmphotography #vintage  #montreux #royalpalacehotel  #selfie </p>

这个伎俩是(这让我暂时搁置了一段时间,直到解决方案找到我这里:http://php.net/manual/en/domnode.removechild.php#90292

您必须使用两个循环来移除标记。第一个生成要删除的标记列表,然后第二个生成删除。