Javascript URL验证-接受没有协议的URL

Javascript URL验证-接受没有协议的URL,javascript,regex,url,Javascript,Regex,Url,我的应用程序中有一个基本的URL验证。现在我正在使用以下代码 //validates whether the given value is //a valid URL function validateUrl(value) { var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ return regexp.test(value);

我的应用程序中有一个基本的URL验证。现在我正在使用以下代码

//validates whether the given value is 
//a valid URL
function validateUrl(value)
{
    var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
    return regexp.test(value);
}

但是现在它不接受没有协议的URL。例如,如果我提供www.google.com,它就不接受。如何修改RegEx使其接受不带协议的URL?

使用
(…)使协议可选?

将正则表达式更改为:

/((ftp|http|https):\/\/)?(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/

我不是regex专家,但用另一个括号括住协议,并在末尾使用问号,应该可以选择:

function validateUrl(value)
{
    var regexp = /((ftp|http|https):\/\/)?(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
    return regexp.test(value);
} 

将第一部分更改为:

(?:(ftp|http|https):)?(?:\/\/)?
(?:
将在不使用捕获组的情况下对内容进行分组(因此实际协议保留在第一组中)


请注意
协议:
//
部分是如何单独可选的-因为
//www.google.com
是一个有效的(相对)URL。

这里有一个用于匹配URL的长正则表达式:

(?i)\b((?:(?:[a-z][\w-]+:)?(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))
(2)以下两种:::::::[a-z[a-z[[[[w-[[w-[[[w-[[[[w-[[[w-[[[w-[[[[w-[[w-[[[w-[[[w-[[[[w-[[[[w-[3]以下以下以下以下几种:::::::::::[1,3}[9-z0-9-10-9-10-9-9-9-5-9-9-9-9%[9-9-9-9-9-9-9-9%[3-9[3-9[3-5]以下以下以下以下以下:::::::::::))))))))))以下以下以下以下以下以下以下以下以下以下两两个::::::::::::::::))))以下以下以下以下((((()))))()\[\]{};:“,«»””)) 扩展版本(有助于理解):

(?xi)
\b
(#捕获1:完整匹配的URL
(?:
(?:[a-z][\w-]+:)?#URL协议和冒号
(?:
/{1,3}#1-3斜杠
|#或
[a-z0-9%]#单个字母或数字或“%”
#(尝试不匹配,例如“URI::Escape”)
)
|#或
www\d{0,3}[.]#“www.”,“wwww1.”,“www2.”…“www999.”
|#或
[a-z0-9.\-]+[.][a-z]{2,4}/#看起来像是域名后跟斜杠
)
(?:#一个或多个:
[^\s()]+#非空格运行,非-()
|#或
\(([^\s()]+\(\([^\s()]+\)*\)\平衡排列,最多两个级别
)+
(?:#结尾为:
\(([^\s()]+\(\([^\s()]+\)*\)\平衡排列,最多两个级别
|#或
[^\s`!()\[\]{};:“,«»”'''.\n不是空格或这些点状字符之一
)
)

这两个URL都来自,但经过了一些修改,使协议成为可选的—您应该阅读该页面以帮助了解它在做什么,并且它还有一个变体,它只匹配基于web的URL,您可能也需要查看一下。

感谢您的回复。很好。您的所有正则表达式都接受@@##$$作为有效URL。有什么想法吗?NLV,你没有指定要我们更正你的正则表达式,你只是问如何更改它以接受任何协议。无论如何,请看下面我的新答案,它给出了一个完整(复杂)的URL验证正则表达式。这将ftp/http/https移动到第2组,并且不接受
//服务器
URL。请看我的编辑-现在它接受
协议://
//
或它们都不接受。您还可以使用
(?:…)
将组从结果中排除。这仍然过于复杂,而且不适用于
http:google.com
(因此,在我的回答中,我只使用了两个可选组)。另外,包装交替的两面的参数是多余的,只会让事情变得更混乱。与hsz的回答一样,这会将ftp/http/https移动到组2,并且不接受
//服务器
URL。同样,如果这个正则表达式用于捕获URL部分,它会创建不必要的组,它错误地将
/
与排除有效URL的协议结合在一起。虽然//google.com有效,但它不是一个有效的URL,我认为大多数人不知道它会起作用,因此从验证中排除此类URL可能非常有用。不是因为它有可能,它必须在每一种形式上都有效。双斜线只是介于两者之间,因为点位于子域、域或TLD之间。双斜线是路径的前缀,而冒号是协议的分隔符-它们是恰好同时出现的两个不同部分。(这在RFC 2396的“3.URI语法组件”中有详细说明)使用//google.com是一个有效的相对Url(同样,请参见RFC 2396的附录“C.1正常示例”),它确实发生在“野外”。不清楚您在那里说什么,这是一个很长的文档-您能参考您所指的特定部分吗?例如,我在Chrome和IE中尝试了
://google.com
,但它不起作用,尽管看起来Firefox接受了它。模式设置只包括协议的名称(如“http”,“ftp”),而不包括冒号。所以即使你的正则表达式也不能正确地划分所有的组。但是,由于NLV只想为有效和通用(而不仅仅是工作)URL使用一个验证正则表达式,因此不需要在斜杠周围使用一个组。内部组捕获
http
ftp
的值,或者其他任何值,外部组(冒号所在的位置)不捕获,并且是使整个内容可选的必要条件。类似地,斜杠周围的非捕获组需要使整个事情成为可选的(它可以使用
\/{0,2}
,但这将允许
/google.com
,这可能是不需要的)。感谢您的努力。让我检查一下。
(?i)\b((?:(?:[a-z][\w-]+:)?(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))
(?xi)
\b
(                           # Capture 1: entire matched URL
  (?:
    (?:[a-z][\w-]+:)?                # URL protocol and colon
    (?:
      /{1,3}                        # 1-3 slashes
      |                             #   or
      [a-z0-9%]                     # Single letter or digit or '%'
                                    # (Trying not to match e.g. "URI::Escape")
    )
    |                           #   or
    www\d{0,3}[.]               # "www.", "www1.", "www2." … "www999."
    |                           #   or
    [a-z0-9.\-]+[.][a-z]{2,4}/  # looks like domain name followed by a slash
  )
  (?:                           # One or more:
    [^\s()<>]+                      # Run of non-space, non-()<>
    |                               #   or
    \(([^\s()<>]+|(\([^\s()<>]+\)))*\)  # balanced parens, up to 2 levels
  )+
  (?:                           # End with:
    \(([^\s()<>]+|(\([^\s()<>]+\)))*\)  # balanced parens, up to 2 levels
    |                                   #   or
    [^\s`!()\[\]{};:'".,<>?«»“”‘’]        # not a space or one of these punct chars
  )
)