0

下面的代码从字符串中检查任何 URL 的文本并将它们转换为可点击的链接。

我正在尝试获取它,以便如果有指向图像的链接,它会在 < a> 标记中添加 rel="image" 。如果有 youtube 视频,它会将 rel="youtube" 添加到 < a> 标签。

如果字符串中只有一个链接,它工作正常。当有多个链接时,所有链接都会获得最后一个链接的 rel。

$text = "http://site.com a site www.anothersite.com/ http://imgur.com/image.png http://youtu.be/UyxqmghxS6M here is another site";

$linkstring = preg_replace('/(http|ftp)?+(s)?:?(\/\/)?+(www.)?((\w|\.)+)+\.(com|org|net|mil|edu|COM|ORG|NET|MIL|EDU|be|info|co)+(\/)?(\S+)?/i', '<a rel="iframe" href="\0">\0</a>', $text ); 
if(preg_match('/((http:\/\/)?(?:youtu\.be\/|(?:[a-z]{2,3}\.)?youtube\.com\/v\/)([\w-]{11}).*|http:\/\/(?:youtu\.be\/|(?:[a-z]{2,3}\.)?youtube\.com\/watch(?:\?|#\!)v=)([\w-]{11}).*)/i', $linkstring, $vresult)) {
    $pattern = "/(http|ftp)?+(s)?:?(\/\/)?+(www.)?((\w|\.)+)+\.(com|org|net|mil|edu|COM|ORG|NET|MIL|EDU|be|info|co)+(\/)?(\S+)?/i";
    $replacement = '<a rel="youtube" href="\0">\0</a>';
    $text2 = preg_replace($pattern, $replacement, $text);
    $type= 'youtube';
} elseif(preg_match('/(http(s?):)?|([\/|.|\w|\s])*\.(?:jpg|gif|png|jpeg|bmp)/i', $linkstring, $vresult)) {
    $pattern = "/(http|ftp)?+(s)?:?(\/\/)?+(www.)?((\w|\.)+)+\.(com|org|net|mil|edu|COM|ORG|NET|MIL|EDU|be|info|co)+(\/)?(\S+)?/i";
    $replacement = '<a rel="image" href="\0">\0</a>';
    $text2 = preg_replace($pattern, $replacement, $text);
    $type= 'image';
} else {
    $type = 'none';
}
echo $text, "<br />";
echo $text2, "<br />";
echo $linkstring, "<br />";
echo $type, "<br />";

我尝试更改 $pattern 以使其匹配与 youtube 或图像链接相同的正则表达式,但最终会在 URL 之后为整个文本创建一个链接。

例子:

$text = "http://site.com a site www.anothersite.com/ http://imgur.com/image.png http://youtu.be/UyxqmghxS6M here is another site";

$linkstring = preg_replace('/(http|ftp)?+(s)?:?(\/\/)?+(www.)?((\w|\.)+)+\.(com|org|net|mil|edu|COM|ORG|NET|MIL|EDU|be|info|co)+(\/)?(\S+)?/i', '<a rel="iframe" href="\0">\0</a>', $text ); 
if(preg_match('/((http:\/\/)?(?:youtu\.be\/|(?:[a-z]{2,3}\.)?youtube\.com\/v\/)([\w-]{11}).*|http:\/\/(?:youtu\.be\/|(?:[a-z]{2,3}\.)?youtube\.com\/watch(?:\?|#\!)v=)([\w-]{11}).*)/i', $linkstring, $vresult)) {
    $pattern = "/((http:\/\/)?(?:youtu\.be\/|(?:[a-z]{2,3}\.)?youtube\.com\/v\/)([\w-]{11}).*|http:\/\/(?:youtu\.be\/|(?:[a-z]{2,3}\.)?youtube\.com\/watch(?:\?|#\!)v=)([\w-]{11}).*)/i";
    $replacement = '<a rel="youtube" href="\0">\0</a>';
    $text2 = preg_replace($pattern, $replacement, $text);
    $type= 'youtube';
} else {
    $type = 'none';
}
4

1 回答 1

0

不幸的是,我无法让您的正则表达式工作,以准确查看您的输出是什么样子(如果您发布结果字符串而不是仅仅描述它们可能会有所帮助)。

但是,您要做的是以下内容。在 if 语句的第一个片段中,您检查字符串是否包含 youtube 链接或图像链接。但是您根本不使用这些信息,而只是再次对整个初始字符串使用 preg_replace 。这当然会替换所有链接,而不仅仅是您之前使用 preg_match 找到的链接(因为该调用完全不相关)。

所以你的第二种方法实际上更好。虽然,我认为在这种情况下你根本不需要 if 子句,因为只有匹配相同模式的字符串部分才会被替换。在链接之后获得完整字符串的原因是 RegExes 中的贪婪。它发生是因为您以 . 结尾两种可能的 youtube 模式.*。这可能只是匹配 URL 的其余部分,但它总是会尽可能多地接收。因为.匹配任何字符,那是字符串的其余部分。所以首先,你需要告诉正则表达式在哪里停止考虑字符。例如,您可以说 URL 以空格或引号结尾。所以而不是

(youtubepattern1).*|(youtubepattern2).*

你可以试试

((youtubepattern1|youtubepattern2).*)["\s]

但是现在贪婪仍然是一个问题,如果 URL 后面有多个引号或字符串后面的空格(因为它会包含直到最后一个空格或引号之前的所有内容)。(在 PHP 的正则表达式方法中)告诉解释器不贪婪地对待 .*,添加一个问号:

((youtubepattern1|youtubepattern2).*?)["\s]

此外,您可能需要将替换从 using 更改\0为 using \1now(因为 \0 将包含结束 URL 的空格或引号)。

于 2012-09-21T06:54:53.887 回答