与正则表达式链接的 PHP URL
Posted
技术标签:
【中文标题】与正则表达式链接的 PHP URL【英文标题】:PHP URL to Link with Regex 【发布时间】:2011-09-17 15:18:42 【问题描述】:我知道我已经在很多地方看到过这种做法,但我需要一些与常规不同的东西。可悲的是,当我在任何地方搜索它时,它都会被埋在关于将链接制作成 html 标记链接的帖子中。我希望 php 函数从链接中删除“http://”和“https://”以及 .* 之后的任何内容,所以基本上我正在寻找的是将 A 变成 B。
A: http://www.youtube.com/watch?v=spsnQWtsUFM
B: <a href="http://www.youtube.com/watch?v=spsnQWtsUFM">www.youtube.com</a>
如果有帮助,这是我当前的 PHP 正则表达式替换函数。
ereg_replace("[[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/]", "<a href=\"\\0\" class=\"bwl\" target=\"_new\">\\0</a>", htmlspecialchars($body, ENT_QUOTES)));
说我完全不了解正则表达式可能也会有所帮助。谢谢!
编辑:当我输入像这样blahblah @987654321@ blah
这样的评论时,我得到像这样<a class="bwl" href="blahblah @987654322@ blah">www.facebook.com</a>
这样的html,它根本不起作用,因为它正在使用链接周围的文本。但是,如果有人只使用链接,它会很好用。这是我将功能更改为此
preg_replace("#^(.*)//(.*)/(.*)$#",'<a class="bwl" href="\0">\2</a>', htmlspecialchars($body, ENT_QUOTES));
【问题讨论】:
总是更喜欢preg*
而不是ereg*
函数,因为ereg*
函数速度慢且已弃用。
How to add anchor tag to a URL from text input的可能重复
【参考方案1】:
这是最简单最干净的方法:
$str = 'http://www.youtube.com/watch?v=spsnQWtsUFM';
preg_match("#//(.+?)/#", $str, $matches);
$site_url = $matches[1];
编辑:我假设 $str 一开始就被检查为一个 URL,所以我把它省略了。此外,我假设所有 URL 都包含“http://”或“https://”。如果 url 的格式是 www.youtube.com/watch?v=spsnQWtsUFM
甚至 youtube.com/watch?v=spsnQWtsUFM
,上面的正则表达式将不起作用!
EDIT2:对不起,我没有意识到您试图替换整个测试中的所有字符串。在这种情况下,这应该按照您想要的方式工作:
$str = preg_replace('#(\A|[^=\]\'"a-zA-Z0-9])(http[s]?://(.+?)/[^()<>\s]+)#i', '\\1<a href="\\2">\\3</a>', $str);
【讨论】:
这也将匹配 ftp://... :) @Tudor Constantin:是的,我只是编辑它说使用这个函数我假设它之前已经被检查为一个有效的 URL。 你的似乎也不适用于我想要做的事情,因为我试图替换用户评论中的所有链接,所以它只显示1
跨度>
我没有意识到 $str 是一个文本片段,而不仅仅是一个确认的 URL。我也没有意识到你想替换所有。我更新了代码。应该像魅力一样工作。
是的,即使有多个链接,它似乎也能完全工作!非常感谢:)【参考方案2】:
我也不是正则表达式专家,
^(.*)//(.*)/(.*)$
<a href="\1//\2/\3">\2</a>
当我尝试在程序员的记事本中用作查找和替换时,这对我有用。
^(.)// 应该提取协议 - 在第二行中称为 \1。 (.)/ 应该提取所有内容,直到第一个 / - 在第二行中称为 \2。 (.*)$ 捕获直到字符串末尾的所有内容。 - 在第二行中称为 \3。
稍后添加
^(.*)( )(.*)//(.*)/(.*)( )(.*)$
\1\2<a href="\3//\4/\5">\4</a> \7
这应该会好一点,但只会替换 1 个 URL
【讨论】:
这可以正常工作(如果在调用它之前检查为有效的 URL)。作为一个合适的 PHP,这将是 preg_replace("#^(.*)//(.*)/(.*)$#",'\2', $str),其中 \0 是整个匹配的字符串。 @stumpx:我不知道你为什么选择这个答案是正确的,但在意识到你的情况之后 1) $str 值没有被检查为有效的 URL 和 2 ) 如果您想替换 $str 中的所有 URL,则此代码根本无法按照您想要的方式工作。首先,它不仅适用于 http(s) 链接,而且适用于 ftp(s) 或 irc(例如)。此外,它只会返回 $str 中最后出现的链接的 HTML 格式链接,而不是字符串的其余部分(任何形状或形式)。 其实这行不通。当我输入像blahblah https://www.facebook.com/?sk=ff&ap=1 blah
这样的评论时,我得到像 <a class="bwl" href="Links dont work https:">www.facebook.com</a>
这样的 html,它根本不起作用。但是,如果有人只提供链接,它会很好用
好的,所以你在评论中有 URL...我发布了表达式,假设字符串只有 URL。在这种情况下,尝试查找 '^(.*)( )(.*)//(.*)/(.*)( )(.*)$' '\1\2\4 \7' 这应该会好一些,但只会替换 1 个 URL。【参考方案3】:
\0 将替换为整个匹配的字符串,而 \x(其中 x 是从 1 开始的 0 以外的数字)将根据括号中的内容和顺序替换为匹配字符串的每个子部分这些组出现。您的解决方案如下:
ereg_replace("[[:alpha:]]+://([^<>[:space:]]+[:alnum:]*)[[:alnum:]/]", "<a href=\"\\0\" class=\"bwl\" target=\"_new\">\\1</a>
虽然我无法对此进行测试,所以请告诉我它是否有效。
【讨论】:
此函数在 PHP 5.3.0 中已被弃用。再用这个功能就不太明智了。最重要的是,表达式比它需要的复杂得多。 这似乎不起作用,它实际上仍然只是使用了整个链接并将数字更改为 2 只是在输出中给了我一个 2 啊,我什至没有看到你的第一条评论,不过谢谢你的解释,我什至没有意识到【参考方案4】:我认为应该这样做(我还没有测试过):
preg_match('/^http[s]?:\/\/(.+?)\/.*/i', $main_url, $matches);
$final_url = '<a href="'.$main_url.'">'.$matches[1].'</a>';
【讨论】:
这不适用于 https 链接。此外,可能不需要首先检查它是否是 URL,因此不需要正则表达式的最后一部分 (/.*)。最后,由于正斜杠在表达式中被大量使用,使用不同的表达式分隔符会更聪明,例如 ;或#。【参考方案5】:我很惊讶没有人记得 PHP 的 parse_url 函数:
$url = 'http://www.youtube.com/watch?v=spsnQWtsUFM';
echo parse_url($url, PHP_URL_HOST); // displays "www.youtube.com"
我想你知道从那里做什么。
【讨论】:
当然……有点忘了这个。我想我已经习惯了 preg_match/preg_replace x)。无论如何, parse_url 将需要更多的代码行。我不知道它将如何与 preg_replace 进行基准测试,但我想,鉴于 PHP 需要构建数组,并且您可能首先需要使用 preg_match_all 来获取文本中的所有 URL,它是不会胜过 preg_replace 函数。 是的,一开始我没有意识到他在文档中进行搜索和替换。我以为他只是在处理一个 URL....【参考方案6】:$result = preg_replace('%(http[s]?://)(\S+)%', '<a href="\1\2">\2</a>', $subject);
【讨论】:
ereg_replace 自 PHP 5.3.0 起已被弃用。现在使用这个功能是不明智的。 @Battle_707,你是对的,我处于自动驾驶模式,只是使用了与海报相同的功能,没有考虑它。我用 preg 更新了我的答案。【参考方案7】:带有正则表达式的代码不能完全工作。
我编写了这段代码。它更全面,但很有效:
在此处查看结果:http://cht.dk/data/php-scripts/inc_functions_links.php
在此处查看源代码:http://cht.dk/data/php-scripts/inc_functions_links.txt
【讨论】:
以上是关于与正则表达式链接的 PHP URL的主要内容,如果未能解决你的问题,请参考以下文章