使用JavaScript检测文本中的URL

arb*_*les 128 javascript regex url

有没有人建议检测一组字符串中的URL?

arrayOfStrings.forEach(function(string){
  // detect URLs in strings and do something swell,
  // like creating elements with links.
});
Run Code Online (Sandbox Code Playgroud)

更新:我使用这个正则表达式进行链接检测...显然几年后.

kLINK_DETECTION_REGEX = /(([a-z]+:\/\/)?(([a-z0-9\-]+\.)+([a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|local|internal))(:[0-9]{1,5})?(\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(\?[a-z0-9+_\-\.%=&]*)?)?(#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)(\s+|$)/gi
Run Code Online (Sandbox Code Playgroud)

完整的助手(可选的Handlebars支持)在要点#1654670.

Cre*_*esh 188

首先,你需要一个与网址匹配的好的正则表达式.这很难做到.看到这里,这里这里:

...几乎任何东西都是有效的URL.有一些标点符号可以将它拆分.没有任何标点符号,您仍然拥有有效的URL.

仔细检查RFC,看看是否可以构建"无效"URL.规则非常灵活.

例如,:::::是一个有效的URL.路径是":::::".一个非常愚蠢的文件名,但有效的文件名.

此外,/////是一个有效的URL.netloc("主机名")是"".路径是"///".再次,愚蠢.也有效.此URL规范化为"///" 等效的URL .

类似的东西"bad://///worse/////" 是完全有效的.愚蠢但有效.

无论如何,这个答案并不是为了给你提供最好的正则表达式,而是用JavaScript来证明如何在文本中进行字符串换行.

好的,让我们使用这个: /(https?:\/\/[^\s]+)/g

再次,这是一个糟糕的正则表达式.它会有很多误报.但是这个例子足够好了.

function urlify(text) {
    var urlRegex = /(https?:\/\/[^\s]+)/g;
    return text.replace(urlRegex, function(url) {
        return '<a href="' + url + '">' + url + '</a>';
    })
    // or alternatively
    // return text.replace(urlRegex, '<a href="$1">$1</a>')
}

var text = "Find me at http://www.example.com and also at http://stackoverflow.com";
var html = urlify(text);

// html now looks like:
// "Find me at <a href="http://www.example.com">http://www.example.com</a> and also at <a href="http://stackoverflow.com">http://stackoverflow.com</a>"
Run Code Online (Sandbox Code Playgroud)

所以总结一下:

$$('#pad dl dd').each(function(element) {
    element.innerHTML = urlify(element.innerHTML);
});
Run Code Online (Sandbox Code Playgroud)

  • "许多误报"的一些例子将大大改善这个答案.否则,未来的Google员工只会留下一些(可能是有效的?)FUD. (3认同)
  • 这很好,但是它会跟踪标点符号"text ="在http://www.example.com和http://stackoverflow.com找到我.有些用户知道这一点,并会在标点之前的URL之后添加一个空格以避免破坏,但我使用的大多数链接器(Gmail,etherpad,phabricator)都会从URL中分隔尾部标点符号. (3认同)

小智 120

这是我最终用作我的正则表达式:

var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
Run Code Online (Sandbox Code Playgroud)

这不包括URL中的尾随标点符号.Crescent的功能就像一个魅力:)所以:

function linkify(text) {
    var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
    return text.replace(urlRegex, function(url) {
        return '<a href="' + url + '">' + url + '</a>';
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 它无法检测到仅以 www 开头的 url。例如:www.facebook.com (7认同)
  • 简单又好看!但是`urlRegex`应该定义为_outside_`linkify`,因为编译它很昂贵. (4认同)
  • 最后,在最明显的情况下真正有效的正则表达式!这个值得一书签。我测试了Google搜索中的数千个示例,直到找到了。 (3认同)
  • @CraZyDroiD 这不是有效的 url,url 必须以 http 或 https 开头 (3认同)
  • 这无法检测完整的 URL:http://disney.wikia.com/wiki/Pua_(Moana) (2认同)

Ada*_*dam 45

我搜索了这个问题很长一段时间,然后我发现有一个Android方法,android.text.util.Linkify,它利用一些相当强大的正则表达式来实现这一目标.幸运的是,Android是开源的.

他们使用一些不同的模式来匹配不同类型的网址.你可以在这里找到它们:http: //grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.0_r1/android/text/util/Regex.java#Regex. 0WEB_URL_PATTERN

如果你只关心与WEB_URL_PATTERN匹配的url,即符合RFC 1738规范的url,你可以使用:

/((?:(http|https|Http|Https|rtsp|Rtsp):\/\/(?:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,64}(?:\:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,25})?\@)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}\.)+(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\:\d{1,5})?)(\/(?:(?:[a-zA-Z0-9\;\/\?\:\@\&\=\#\~\-\.\+\!\*\'\(\)\,\_])|(?:\%[a-fA-F0-9]{2}))*)?(?:\b|$)/gi;
Run Code Online (Sandbox Code Playgroud)

以下是来源的全文:

"((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+ "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
+ "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}\\.)+"   // named host
+ "(?:"   // plus top level domain
+ "(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])"
+ "|(?:biz|b[abdefghijmnorstvwyz])"
+ "|(?:cat|com|coop|c[acdfghiklmnoruvxyz])"
+ "|d[ejkmoz]"
+ "|(?:edu|e[cegrstu])"
+ "|f[ijkmor]"
+ "|(?:gov|g[abdefghilmnpqrstuwy])"
+ "|h[kmnrtu]"
+ "|(?:info|int|i[delmnoqrst])"
+ "|(?:jobs|j[emop])"
+ "|k[eghimnrwyz]"
+ "|l[abcikrstuvy]"
+ "|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])"
+ "|(?:name|net|n[acefgilopruz])"
+ "|(?:org|om)"
+ "|(?:pro|p[aefghklmnrstwy])"
+ "|qa"
+ "|r[eouw]"
+ "|s[abcdeghijklmnortuvyz]"
+ "|(?:tel|travel|t[cdfghjklmnoprtvwz])"
+ "|u[agkmsyz]"
+ "|v[aceginu]"
+ "|w[fs]"
+ "|y[etu]"
+ "|z[amw]))"
+ "|(?:(?:25[0-5]|2[0-4]" // or ip address
+ "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(?:25[0-5]|2[0-4][0-9]"
+ "|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1]"
+ "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+ "|[1-9][0-9]|[0-9])))"
+ "(?:\\:\\d{1,5})?)" // plus option port number
+ "(\\/(?:(?:[a-zA-Z0-9\\;\\/\\?\\:\\@\\&\\=\\#\\~"  // plus option query params
+ "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
+ "(?:\\b|$)";
Run Code Online (Sandbox Code Playgroud)

如果你想要真正喜欢,你也可以测试电子邮件地址.电子邮件地址的正则表达式是:

/[a-zA-Z0-9\\+\\.\\_\\%\\-]{1,256}\\@[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}(\\.[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25})+/gi
Run Code Online (Sandbox Code Playgroud)

PS:截至2007年6月,上述正则表达式支持的顶级域名是最新的.要获得最新列表,您需要查看https://data.iana.org/TLD/tlds-alpha-by-domain.txt.

  • 这很好,但我不确定我是否会使用它.对于大多数用例,我宁愿接受一些误报而不是使用依赖于硬编码TLD列表的方法.如果您在代码中列出TLD,那么您可以保证它有一天会过时,如果我可以避免,我宁愿不在我的代码中构建强制性的未来维护. (3认同)
  • 由于您具有不区分大小写的正则表达式,因此不必指定`a-zA-Z`和`http | https | Http | Https | rtsp | Rtsp`。 (2认同)
  • 这种情况在101%的情况下都有效,不幸的是它也找到了没有空格的网址.如果我在hello@mydomain.com上进行一场比赛,那就会捕获'mydomain.com'.有没有办法改进它,只有在它之前有空间才能捕获它? (2认同)

h0m*_*yun 19

基于Crescent Fresh的答案

如果你想检测带有http:// OR 而没有http://和www的链接.你可以使用以下

function urlify(text) {
    var urlRegex = /(((https?:\/\/)|(www\.))[^\s]+)/g;
    //var urlRegex = /(https?:\/\/[^\s]+)/g;
    return text.replace(urlRegex, function(url,b,c) {
        var url2 = (c == 'www.') ?  'http://' +url : url;
        return '<a href="' +url2+ '" target="_blank">' + url + '</a>';
    }) 
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*tor 17

NPM上的这个库看起来非常全面https://www.npmjs.com/package/linkifyjs

Linkify是一个小而全面的JavaScript插件,用于以纯文本格式查找URL并将其转换为HTML链接.它适用于所有有效的URL和电子邮件地址.

  • 我刚刚完成了在我的项目中实现linkifyjs,这太棒了.Linkifyjs应该是这个问题的答案.另一个要看的是https://github.com/twitter/twitter-text (4认同)

Kas*_*der 6

let str = 'https://example.com is a great site'
str.replace(/(https?:\/\/[^\s]+)/g,"<a href='$1' target='_blank' >$1</a>")
Run Code Online (Sandbox Code Playgroud)

短代码大工作!...

结果:-

 <a href="https://example.com" target="_blank" > https://example.com </a>
Run Code Online (Sandbox Code Playgroud)


Gau*_*rma 5

可以进一步改进功能以渲染图像:

function renderHTML(text) { 
    var rawText = strip(text)
    var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;   

    return rawText.replace(urlRegex, function(url) {   

    if ( ( url.indexOf(".jpg") > 0 ) || ( url.indexOf(".png") > 0 ) || ( url.indexOf(".gif") > 0 ) ) {
            return '<img src="' + url + '">' + '<br/>'
        } else {
            return '<a href="' + url + '">' + url + '</a>' + '<br/>'
        }
    }) 
} 
Run Code Online (Sandbox Code Playgroud)

或者链接到fiull尺寸图像的缩略图:

return '<a href="' + url + '"><img style="width: 100px; border: 0px; -moz-border-radius: 5px; border-radius: 5px;" src="' + url + '">' + '</a>' + '<br/>'
Run Code Online (Sandbox Code Playgroud)

这里是strip()函数,它通过删除任何现有的html来预处理文本字符串以实现一致性.

function strip(html) 
    {  
        var tmp = document.createElement("DIV"); 
        tmp.innerHTML = html; 
        var urlRegex =/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;   
        return tmp.innerText.replace(urlRegex, function(url) {     
        return '\n' + url 
    })
} 
Run Code Online (Sandbox Code Playgroud)