如何删除 <a> 文本中包含主题标签的标签?
How to remove <a> tags that contain hashtags in their text?
我想删除 链接的主题标签
我不想删除没有链接的主题标签。
我不想删除其他链接。
例如:
<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>
我想成为:
<p><a href="/user/username" >Username</a> #filmphotography #vintage #montreux #royalpalacehotel #selfie </p>
此代码无效:
$html = preg_replace('#<a(.*?)>#(.*?)</a>#is', '', $html);
使用字符集而不是量词的简短回答
<a[^>]*>#[^<#]*<\/a>
效率更高,因为不能回溯,避免回溯不需要的结果。
(.*?)
惰性量词意味着最短的匹配,但在回溯的情况下,它将包含更大的匹配,因为开始得太早。
如果出现意外匹配,正则表达式可能会得到改进。
正如 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)
您必须使用两个循环来删除标签。第一个循环生成要删除的标签列表,然后第二个循环执行删除。
我想删除 链接的主题标签
我不想删除没有链接的主题标签。
我不想删除其他链接。
例如:
<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>
我想成为:
<p><a href="/user/username" >Username</a> #filmphotography #vintage #montreux #royalpalacehotel #selfie </p>
此代码无效:
$html = preg_replace('#<a(.*?)>#(.*?)</a>#is', '', $html);
使用字符集而不是量词的简短回答
<a[^>]*>#[^<#]*<\/a>
效率更高,因为不能回溯,避免回溯不需要的结果。
(.*?)
惰性量词意味着最短的匹配,但在回溯的情况下,它将包含更大的匹配,因为开始得太早。
如果出现意外匹配,正则表达式可能会得到改进。
正如 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)
您必须使用两个循环来删除标签。第一个循环生成要删除的标签列表,然后第二个循环执行删除。