preg_replace file_get_contents中不包含单词的所有链接

时间:2013-05-12 21:25:34

标签: php regex preg-replace negative-lookahead

我正在将页面读入变量,我想禁用地址中不包含“remedy”一词的所有链接。到目前为止我的代码抓住了所有链接,包括“补救”。我做错了什么?

$page = preg_replace('~<a href=".*?(?!remedy).*?".*?>(.*?)</a>~i', '<font color="#808080">$1</font>', $page);

- 解决方案 -

$page = preg_replace('~<a href="(.(?!remedy))*?".*?>(.*?)</a>~i', '<font color="#808080">$2</font>', $page);

2 个答案:

答案 0 :(得分:3)

尝试~<a href="(.(?!remedy))*?".*?>(.*?)</a>~i

对于这个问题,你做错了什么:正则表达式在任何可能的情况下匹配,并且对于每个网址(即使包含remedy),可以匹配'~<a href=".*?(?!remedy).*?".*?>(.*?)</a>~i',因为你没有指定 remedy可能未包含在属性中的任何位置,但是您指定必须有任何/不存在(.*?remedy 除了那些以<a href="remedy"开头的网址外,任何网址都是如此。希望人们能理解......

答案 1 :(得分:0)

我可能会用这个:

<a href="(?:(?!remedy)[^"])*"[^>]*>([^<]*)</a>

最有趣的部分是:

"(?:(?!remedy)[^"])*"

每次[^"]即将消耗另一个角色时,它会向前瞻产生,因此它确认它不是单词remedy的第一个字符。使用[^"]代替.会阻止它查看结束引号之外的任何内容。我也冒昧地用否定的角色类替换你的.*?。这有同样的目的,使匹配“保持”在您想要匹配的区域。它也更高效,更强大。

当然,我假设<a>元素的内容是纯文本,其中没有更多元素嵌套。事实上,这只是我所做的许多简化假设之一。如果没有它们,您就无法将HTML与正则表达式匹配。