从字符串中提取 URL
Posted
技术标签:
【中文标题】从字符串中提取 URL【英文标题】:Extract URL from string 【发布时间】:2011-05-22 09:24:03 【问题描述】:我正在尝试找到一种可靠的解决方案来从字符串中提取 url。我有一个网站,用户可以在其中回答问题,并在来源框中输入他们的信息来源,我允许他们输入网址。我想提取该网址并使其成为超链接。类似于 Yahoo Answers 的做法。
有谁知道可以做到这一点的可靠解决方案吗?
我发现的所有解决方案都适用于某些 URL,但不适用于其他 URL。
谢谢
【问题讨论】:
【参考方案1】:John Gruber 拥有spent a fair amount of time 完善了“一个正则表达式来统治所有这些”以进行链接检测。使用preg_replace()
如其他答案中所述,使用以下正则表达式应该是检测链接的最准确(如果不是最准确)方法之一:
(?i)\b((?:[a-z][\w-]+:(?:/1,3|[a-z0-9%])|www\d0,3[.]|[a-z0-9.\-]+[.][a-z]2,4/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\];:'".,<>?«»“”‘’]))
如果你只想匹配 HTTP/HTTPS:
(?i)\b((?:https?://|www\d0,3[.]|[a-z0-9.\-]+[.][a-z]2,4/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\];:'".,<>?«»“”‘’]))
【讨论】:
正是我想要的!谢谢。 对于任何希望将所有子模式转换为非捕获并且正斜杠转义的人:\b(?:(?:[az][\w-]+:(?: \/1,3|[a-z0-9%])|www\d0,3[.]|[a-z0-9.\-]+[.][az]2, 4\/)(?:[^\s()]+|((?:[^\s()]+|(?:([^\s()]+)) )*))+(?:((?:[^\s()]+|(?:([^\s()]+)))*)|[^\s`!( )[];:'".,?«»“”''])) TLD 可能有超过 4 个字符,请参阅:iana.org/domains/root/db 我们如何在 preg 中使用这个正则表达式?我的意思是,因为它有"
和 '
代码不能正常工作,比如:preg_match('(?i)\b......]))', $str)
- 所有代码似乎都被注释了。
不工作。 Preg_match 和 preg_match_all 每次都失败,即使在删除单引号/双引号后也是如此【参考方案2】:
$string = preg_replace('/https?:\/\/[^\s"<>]+/', '<a href="$0" target="_blank">$0</a>', $string);
它只匹配 http/https,但这确实是您想要转换为链接的唯一协议。如果你想要其他人,你可以这样改变它:
$string = preg_replace('/(https?|ssh|ftp):\/\/[^\s"]+/', '<a href="$0" target="_blank">$0</a>', $string);
【讨论】:
您可能还想排除<
或在匹配的字符串上应用 htmlspecialchars
以避免代码注入。
很好,但是如果您查看表达式,它允许除空格和"
之外的任何内容。我相信这消除了任何 HTML 注入。
Bron:不,您使用的匹配值不仅作为属性值,还作为元素文本内容。【参考方案3】:
url 有很多边缘情况。像 url 可以包含括号或不包含协议等。这就是为什么正则表达式是不够的。
我创建了一个可以处理大量边缘情况的 php 库:Url highlight。
您可以从字符串中提取网址或直接突出显示它们。 示例:
<?php
use VStelmakh\UrlHighlight\UrlHighlight;
$urlHighlight = new UrlHighlight();
// Extract urls
$urlHighlight->getUrls("This is example http://example.com.");
// return: ['http://example.com']
// Make urls as hyperlinks
$urlHighlight->highlightUrls('Hello, http://example.com.');
// return: 'Hello, <a href="http://example.com">http://example.com</a>.'
更多详情请见readme。对于覆盖的 url 案例,请参阅test。
【讨论】:
【参考方案4】:雅虎!当链接写得正确并与其他文本分开时,Answers 可以很好地识别链接,但它不能很好地分离尾随标点符号。例如The links are @987654321@, @987654322@, and @987654323@.
将在前两个中包含逗号,在第三个中包含句点。
但如果这是可以接受的,那么像这样的模式应该这样做:
\<http:[^ ]+\>
看起来***的解析器更好。是开源的吗?
【讨论】:
更聪明,但仍不完美。错过了 ssh+svn 之类的东西。【参考方案5】:这段代码对我有用。
function makeLink($string)
/*** make sure there is an http:// on all URLs ***/
$string = preg_replace("/([^\w\/])(www\.[a-z0-9\-]+\.[a-z0-9\-]+)/i", "$1http://$2",$string);
/*** make all URLs links ***/
$string = preg_replace("/([\w]+:\/\/[\w-?&;#~=\.\/\@]+[\w\/])/i","<a target=\"_blank\" href=\"$1\">$1</a>",$string);
/*** make all emails hot links ***/
$string = preg_replace("/([\w-?&;#~=\.\/]+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]2,3|[0-9]1,3)(\]?))/i","<a href=\"mailto:$1\">$1</a>",$string);
return $string;
【讨论】:
为什么将 tld 限制为 3 个字符?看看:iana.org/domains/root/db以上是关于从字符串中提取 URL的主要内容,如果未能解决你的问题,请参考以下文章