我收到格式为html的文本。我想限制锚标记的网址只能从我的域名替换旧链接“xxx”(或smth'其他)。
输入:“<a href='otherdomain'>text</a>
”
输出:“xxx”
我正在使用正则表达式实现这一点,虽然我有点困在这里:
$pattern ='/<a.*href=[\'|\"]http.?:\/\/[^mydomain.*\"\']*[\'|\"].*<\/a>/i';
$replace ='xxx';
echo preg_replace($pattern, $replace, $string);
这里有什么问题?
答案 0 :(得分:2)
当你执行[^mydomain.*\"\']
时,你说“匹配任何字符,除了字面'm','y','d','o',...,'。','*'等
尝试类似:
#<a [^>]*\bhref=(['"])http.?://((?!mydomain)[^'"])+\1 *>.*?</a>#i
注意:
a.*href
转为a [^>]*\bhref
,以确保'a'和'href'是完整的单词,并且正则表达式与多个标签不匹配。 /
((?!mydomain)[^'"])+
。这意味着“匹配[^'”] +不是mydomain“。(?!
被称为负面预测。\1
。这可以确保URL的结束引号与开始引号相同(请参阅第一组括号捕获['"]
?)。如果你愿意的话,没有它你可能没问题。对于PHP(更新,因为我总是在需要在PHP中转义反斜杠时混淆 - 请参阅下面的@ GlitchMr评论):
$pattern = '#<a [^>]*\bhref=([\'"])http.?://((?!mydomain)[^\'"])+\1 *>.*?</a>#i';
在行动here中查看,您可以根据自己的需要进行调整。
答案 1 :(得分:2)
这是我正在使用的代码的一部分。它正在使用用户函数来更改正则表达式挖出的文本。祝你好运:)
class RedirectLinks {
/**
* Callback used by convert_external_links_to_internal on each url found
*
* @param array $matches
* @return string
*/
public static function urlMatchCallback($matches)
{
if (stripos($matches[1], 'http://') === false ||
stripos($matches[1], 'example.com') !== false
) {
return $matches[0]; // do not modify
}
// encrypt url for redirection
$sURL = $matches[1];
return "href=\"#\" onclick=\"showmessage('$sURL');\"";
}
/**
* Converts external links in text to internal ones
*
* @param string $str - text
* @return the processed text
*/
public static function convertExternalLinksToInternal($str) {
// convert external links to internal redirections
$str = preg_replace_callback("/href=\"([^\"]*)\"/is", 'RedirectLinks::urlMatchCallback', $str);
return $str;
}
}
答案 2 :(得分:1)
(虽然没有理由不解释某事。)
如果你想匹配'除了'之外的任何东西,那么你通常想要使用一个断言;在你的情况下negative lookahead assertion:
(?!mydomain\.com).*?
这将匹配.*?
任何内容,但是在它之前的不允许值。
另请注意:
[\"\']
而不是[\'|\"]
。替代标志在字符类中没有意义。.*
通常应该.*?
不能过于宽泛地匹配。[^>]*
是标记内匹配的常用习惯用法。#<a...*>#i
代替/
以避免转义。答案 3 :(得分:0)
[]
是字符集合运算符。
$pattern ='!<a\s.*?\shref\s*=\s*([\'"])https?:://mydomain.*?\1.*?</a>!is';
注意:
\/