PHP正则表达式将纯文本URL转换为链接,除非它已经存在

时间:2017-03-21 01:03:28

标签: php regex

我有一个php字符串$ tweet,看起来像这样......

This is a sample tweet https://tr.co/sdfhnjn3

但有时它看起来像这样......

This is a sample tweet <a href="https://tr.co/sdfhnjn3">https://tr.co/sdfhnjn3</a>

我希望将所有https://tr.co链接转换为实际的href链接,除非它们已经采用该格式。

我知道我可以使用Regex转换链接,但我是否也可以检查它们是否已经是使用它的链接?

3 个答案:

答案 0 :(得分:1)

要匹配并替换只有尚未链接的网址,请尝试使用此正则表达式:~(?<!href=['"])https?://[\w/._\-&?]*(?!</a>)(?=[^\w/._\-&])~gs

您可以在此处查看演示:https://regex101.com/r/BF8HBO/1

然后将其与preg_replace

一起使用
$string = preg_replace('~(?<!href=['"])https?://[\w/._\-&?]*(?!</a>)(?=[^\w/._\-&])~gs', '<a href="$0">$0</a>', $string);`;
  

注意:也请在regex101中检查替换面板,看看链接是否仅在尚未放置的情况下放置。

<强>详情:

  • 我使用~作为分隔符,因为它在正则表达式主体中不常遇到,因此您不需要像/
  • 那样经常转义
  • (?<!href=['"])这是一个负面的背后隐藏,可确保链接前面没有href=以及'"
  • https?://[\w/._\-&?]*匹配以http://https://
  • 开头的链接
  • [\w/._\-&?]*这匹配任何字母数字字符或其中一个/._?&-通常出现在链接中的字母
  • (?!</a>)这是一个负面的预测,确保链接后面没有结尾</a>
  • (?=[^\w/._\-&])这是一个积极的先行,确保链接后的下一个字符不是/._-&之一,也不是字母数字字符(否则它们应该是链接的一部分)
  

另一个注意事项: PHP有一个很好的正则表达式引擎(PCRE),允许外观,尤其是外观!不幸的是,这不是javascript等其他语言的情况。但总有一个(复杂的)解决方法! :)

     

同样,lookbehinds必须有一个固定宽度的字符,而不像前瞻。

答案 1 :(得分:0)

此代码将使用指向该URL的链接替换所提供的$ message中的任何url

$message = preg_replace('$(\s|^)(https?://[a-z0-9_./?=&-]+)(?![^<>]*>)$i', ' <a href="$2" target="_blank">$2</a> ', $message." ");

事实上,你也可以转换没有协议(http)部分的网址,只要它以www开头,它就可以传递一个有效的网址。

$message = preg_replace('$(\s|^)(www\.[a-z0-9_./?=&-]+)(?![^<>]*>)$i', '<a target="_blank" href="http://$2"  target="_blank">$2</a> ', $message." ");

答案 2 :(得分:0)

您无需使用极其复杂的语法来尝试匹配网址的各个部分,就可以使用(*SKIP)(*FAIL)取消已标记的网址的资格,然后仅匹配您域中的网址。

代码:(Demo)(Regex101

$tweets = [
    'This is a sample tweet https://tr.co/sdfhnjn3',
    'This is a sample tweet <a href="https://tr.co/sdfhnjn3">https://tr.co/sdfhnjn3</a>',
    'This is a sample tweet https://example.com/sdfhnjn3',
    'This is a sample tweet <a href="https://example.com/sdfhnjn3">https://example.com/sdfhnjn3</a>'
];

var_export(preg_replace('~<a [^>]+>.*?</a>(*SKIP)(*FAIL)|https?://(?:www)?tr.co/\S*~', '<a href="$0">$0</a>', $tweets));

输出:

array (
  0 => 'This is a sample tweet <a href="https://tr.co/sdfhnjn3">https://tr.co/sdfhnjn3</a>',
  1 => 'This is a sample tweet <a href="https://tr.co/sdfhnjn3">https://tr.co/sdfhnjn3</a>',
  2 => 'This is a sample tweet https://example.com/sdfhnjn3',
  3 => 'This is a sample tweet <a href="https://example.com/sdfhnjn3">https://example.com/sdfhnjn3</a>',
)

*只有第一个元素实际被更新,其他元素没有资格。