我一直在尝试遍历一个字符串并找到并用一个链接替换 ​​URL,这是我到目前为止所提出的,它似乎在大多数情况下工作得很好,但是有一些我想要的东西抛光。它也可能不是最好的执行方式。

我已经在 SO 上阅读了很多关于此的主题,尽管它有很大帮助,但我仍然需要解决它的松散问题。

我在字符串中运行了两次。我第一次用html标签替换bbtags;第二次我运行字符串并用链接替换文本网址:

$body_str = preg_replace('/\[url=(.+?)\](.+?)\[\/url\]/i', '<a href="\1" rel="nofollow" target="_blank">\2</a>', $body_str);

$body_str = preg_replace_callback(
    '!(?:^|[^"\'])(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?!',
    function ($matches) {
        return strpos(trim($matches[0]), 'thisone.com') == FALSE ?
        '<a href="' . ltrim($matches[0], " \t\n\r\0\x0B.,@?^=%&amp;:/~\+#'") . '" rel="nofollow" target="_blank">' . ltrim($matches[0], "\t\n\r\0\x0B.,@?^=%&amp;:/~\+#'") . '</a>' :
        '<a href="' . ltrim($matches[0], " \t\n\r\0\x0B.,@?^=%&amp;:/~\+#'") . '">' . ltrim($matches[0], "\t\n\r\0\x0B.,@?^=%&amp;:/~\+#'") . '</a>';
    },
    $body_str
);

到目前为止,我发现的几个问题是它倾向于在 'http' 等之前立即获取字符,例如一个空格/逗号/冒号等,这打破了链接。因此,我使用 preg_replace_callback 来解决这个问题并修剪一些会破坏链接的不需要的字符。

另一个问题是,为了避免通过匹配已经在 A 标签中的 url 来破坏链接,我目前排除以引号、双引号开头的 url,我宁愿使用 href='|href="进行排除。

任何提示和建议将不胜感激

最佳答案

首先,我允许自己重构一下您的代码,使其更易于阅读和修改:

函数 urltrim($str) {
return ltrim($str, "\t\n\r\0\x0B.,@?^=%&:/~\+#'");
}
函数 addlink($str,$nofollow=true) {
返回 '​​';
}
功能检查站点($ str){
返回 strpos(trim($str), 'thisone.com') == FALSE ? addlink($str) : addlink($str,false);
}

$body_str = preg_replace('/\[url=(.+?)\](.+?)\[\/url\]/i', '\2', $body_str);

$body_str = preg_replace_callback(
'!(?:^|[^"\'])(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?!',
功能($匹配){
返回检查站点($matches[0]);
},

$body_str
);

之后我改变了你处理链接的方式:

  • 我认为 URL 是一个单词(= 所有字符,直到找到空格或\n 或\t (=\s))
  • 我改了匹配方式,匹配字符串前面是否存在href=
  • 如果它存在那么我什么都不做,它已经是一个链接
  • 如果没有 href= 存在,那么我替换链接
  • 所以 urltrim 方法不再有用,因为我没有在 http
  • 之前吃掉第一个字符
  • 当然,我使用 urlencode 对 url 进行编码并避免 html 注入(inject)

  • 函数 urltrim($str) {
    返回 $str;
    }
    函数 addlink($str,$nofollow=true) {
    $url = preg_replace("#(https?)%3A%2F%2F#","$1://",urlencode(urltrim($str)));
    返回 '​​';
    }
    功能检查站点($ str){
    返回 strpos(trim($str), 'thisone.com') == FALSE ? addlink($str) : addlink($str,false);
    }

    $body_str = preg_replace('/\[url=(.+?)\](.+?)\[\/url\]/i', '\2', $body_str);

    $body_str = preg_replace_callback(
    '!(|href=)(["\']?)(https?://[^\s]+)!',
    功能($匹配){
    如果 ($matches[1]) {
    # 如果href=存在,不要做任何事情,返回原始字符串
    返回 $matches[0];
    } 别的 {
    # 添加前一个字符("或 ')和链接
    返回 $matches[2].checksite($matches[3]);
    }
    },
    $body_str
    );

    我希望这可以帮助您完成您的项目。
    告诉我们是否有帮助。

    再见。

    关于php - 查找和替换文本块中的 URL,但排除链接标签中的 URL,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18123873/

    10-13 07:46
    查看更多