正则表达式用链接替换url并添加特定的rel

时间:2012-09-21 01:01:18

标签: php regex

以下代码检查字符串中的文本是否包含任何网址,并将其转换为可点击的链接。

我试图得到它,以便如果有图像的链接,它会在<中添加rel =“image”。一个>标签。如果有YouTube视频,则会将rel =“youtube”添加到<一个>标签

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

$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或image链接匹配相同的正则表达式,但最终会在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';
}

1 个答案:

答案 0 :(得分:0)

不幸的是,我无法让你的RegExes工作,看看输出的确切结果(如果你发布结果字符串而不是仅仅描述它们,可能会有帮助)。

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

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

(youtubepattern1).*|(youtubepattern2).*

你可以尝试

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

但是现在贪婪仍然是一个问题,如果在URL后面有一个以上的引号或者后面的字符串中有更多的空格(因为那时它将包括所有内容,直到最后一个空格或引号)。 (在PHP的正则表达式方法中)告诉解释器要处理。*不合理地,添加一个问号:

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

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