在JavaScript中是否有一种方法来检查字符串是否是URL?

regex被排除在外,因为URL很可能写成stackoverflow;也就是说,它可能没有。com, WWW或http。


当前回答

我认为使用本地URL API比@pavlo建议的复杂正则表达式模式更好。虽然它有一些缺点,但我们可以通过一些额外的代码来修复。对于以下有效url,此方法失败。

//cdn.google.com/script.js

我们可以预先添加缺失的协议来避免这种情况。它也无法检测以下无效的url。

http://w
http://..

那么为什么要检查整个url呢?我们可以检查定义域。我借用正则表达式从这里验证域。

function isValidUrl(string) {
    if (string && string.length > 1 && string.slice(0, 2) == '//') {
        string = 'http:' + string; //dummy protocol so that URL works
    }
    try {
        var url = new URL(string);
        return url.hostname && url.hostname.match(/^([a-z0-9])(([a-z0-9-]{1,61})?[a-z0-9]{1})?(\.[a-z0-9](([a-z0-9-]{1,61})?[a-z0-9]{1})?)?(\.[a-zA-Z]{2,4})+$/) ? true : false;
    } catch (_) {
        return false;
    }
}

主机名属性是javascript:void(0)的空字符串,所以它也适用于此,你也可以添加IP地址验证器。我最喜欢坚持使用本地API,并希望它在不久的将来开始支持一切。

其他回答

我不能评论最接近#5717133的帖子,但下面是我想出如何让@tom-gullen正则表达式工作的方法。

/^(https?:\/\/)?((([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|((\d{1,3}\.){3}\d{1,3}))(\:\d+)?(\/[-a-z\d%_.~+]*)*(\?[;&a-z\d%_.~+=-]*)?(\#[-a-z\d_]*)?$/i

和我一起工作

function isURL(str) {
  var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
  var pattern = new RegExp(regex); 
return pattern.test(str);
}

(我没有代表对ValidURL的例子发表评论;因此,把这个作为一个答案。)

虽然不鼓励使用协议相对URL(协议相对URL),但有时确实会使用它们。要用正则表达式验证这样的URL,协议部分可以是可选的,例如:

function isValidURL(str) {
    var pattern = new RegExp('^((https?:)?\\/\\/)?'+ // protocol
        '(?:\\S+(?::\\S*)?@)?' + // authentication
        '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
        '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
        '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
        '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
        '(\\#[-a-z\\d_]*)?$','i'); // fragment locater
    if (!pattern.test(str)) {
        return false;
    } else {
        return true;
    }
}

正如其他人指出的那样,正则表达式似乎不是验证url的最佳方法。

2020年更新。 为了扩展@iamnewton和@ fernando Chavez Herrera的精彩回答,我已经开始看到@被用于url的路径。

所以更新后的正则表达式是:

RegExp('(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+@]*)*(\\?[;&a-z\\d%_.~+=-]*)?(\\#[-a-z\\d_]*)?$', 'i');

如果你想在查询字符串和哈希中允许它,使用:

RegExp('(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+@]*)*(\\?[;&a-z\\d%_.~+=-@]*)?(\\#[-a-z\\d_@]*)?$', 'i');

话虽如此,我不确定是否有白皮书规则禁止在查询字符串或哈希中使用@。

有几个使用URL构造函数的测试,没有描述输入是字符串还是URL对象。

// Testing whether something is a URL
function isURL(url) {
    return toString.call(url) === "[object URL]";
}

// Testing whether the input is both a string and valid url:
function isUrl(url) {
    try {
        return toString.call(url) === "[object String]" && !!(new URL(url));
    } catch (_) {
        return false;  
    }
}