我有一个包含链接的字符串。我希望我的php做不同的事情与我的链接,这取决于url。
答:
function fixLinks($text)
{
$links = array();
$text = strip_tags($text);
$pattern = '!(https?://[^'s]+)!';
if (preg_match_all($pattern, $text, $matches)) {
list(, $links) = ($matches);
}
$i = 0;
$links2 = array();
foreach($links AS $link) {
if(strpos($link,'youtube.com') !== false) {
$search = "!(http://.*youtube'.com.*v=)?([a-zA-Z0-9_-]{11})(&.*)?!";
$youtube = '<a href="youtube.php?id=''2" class="fancy">http://www.youtube.com/watch?v=''2</a>';
$link2 = preg_replace($search, $youtube, $link);
} else {
$link2 = preg_replace('@(https?://([-'w'.]+)+(:'d+)?(/(['-'w/_'.]*('?'S+)?)?)?)@', '<a href="$1" target="_blank"><u>$1</u></a>', $link);
}
$links2[$i] = $link2;
$i++;
}
$text = str_replace($links, $links2, $text);
$text = nl2br($text);
return $text;
}
首先,放弃eregi
。它已被弃用,很快就会消失。
那么,在一次传递中完成这一点可能有点过分了。我认为你最好把它分成三个阶段。
第1阶段对输入进行正则表达式搜索,找到所有看起来像链接的内容,并将其存储在列表中。
阶段2遍历列表,检查链接是否指向youtube (parse_url
对此非常有用),并将合适的替换到第二个列表中。
阶段3:您现在有两个列表,一个包含原始匹配项,一个包含所需的替换项。在原始文本上运行str_replace,为搜索参数提供匹配列表,为替换参数提供替换列表。
这种方法有几个优点:
- 用于提取链接的正则表达式可以保持相对简单,因为它不需要考虑特殊的主机名
- 更容易调试;您可以在阶段3之前转储搜索和替换数组,并查看它们是否包含您所期望的
- 因为你一次执行所有的替换,你避免了重叠匹配或替换一段已经替换的文本的问题(毕竟,被替换的文本仍然包含一个URL,你不想再替换它)
tdammers的答案是好的,但另一种选择是使用preg_replace_callback
。如果你这样做,那么过程就会发生一些变化:
- 创建一个正则表达式来匹配所有链接,与他的第1阶段相同
- 在回呼中搜索YouTube视频id。这将需要运行第二个
preg_match
,这是(在我看来)该技术的最大问题。 - 根据是否为YouTube返回替换字符串。
代码看起来像这样:
function replaceem($matches) {
$url = $matches[0];
preg_match('~youtube'.com.*v=(['w'-]{11})~', $url, $matches);
return isset($matches[0]) ?
'<a href="youtube.php?id='.$matches[1].'" class="fancy">'.
'http://www.youtube.com/watch?v='.$matches[1].'</a>' :
'<a href="'.$url.'" title="Åben link" alt="Åben link" '.
'target="_blank">'.$url.'</a>';
}
$text = preg_replace_callback('~(?:f|ht)tps?://[^'s]+~', 'replaceem', $text);