正则表达式被排除在外,因为该URL最有可能像
stackoverflow
一样写;也就是说,它可能没有.com
,www
或http
。#1 楼
答案相关的问题:Javascript正则表达式URL匹配
或来自Devshed的此正则表达式:
评论
@Bruno:很有可能它们在内部用单独的标题和URL保存,例如{title:“ Stackoverflow”,uri:“ http://stackoverflow.com”}更新:实际上,请参见code.google.com/chrome/ extensions / bookmarks.html
– Marcel Korpel
2011年4月19日在13:55
尝试使用您的示例。但是我在萤火虫上看到一个错误,说无效的量词。任何想法?
–西西尔
2012年7月10日18:49
函数返回:SyntaxError:无效的正则表达式:/ ^(https?://)?(((([[a-zd]([a-zd-] * [a-zd])*)。)+ [az] { 2,} |((d {1,3}。){3} d {1,3}))(:d +)?(/ [-a-zd%_。〜+] *)*(?[; &a-zd%_。〜+ =-] *)?(#[-a-zd _] *)?$ /:无效的Google Chrome浏览器(版本30.0.1599.101)(Mac OS X:10.8.5)
– dimitru博士
13-10-19在13:37
请注意,如果将字符串用作RegExp的参数,则必须将反斜杠转义两次-否则会出现诸如无效组之类的错误。
–凯尔
2015年6月5日在16:13
在Firefox 52.0.2中,使用“长”字符串(实际上还不算太久,40个字符就足够了)的测试速度非常慢,以至于我不得不终止脚本。不知道这是Firefox错误还是表达式本身有问题。
–youen
17年4月27日在12:31
#2 楼
如果要检查字符串是否为有效的HTTP URL,可以使用URL
构造函数(它将抛出格式错误的字符串):function isValidHttpUrl(string) {
let url;
try {
url = new URL(string);
} catch (_) {
return false;
}
return url.protocol === "http:" || url.protocol === "https:";
}
请注意,根据RFC 3886,URL必须以方案开头(不是限于http / https),e。 g .:
www.example.com
无效的URL(丢失方案)javascript:void(0)
是有效的URL,尽管不是HTTP的http://..
是有效URL,主机为..
(是否解析取决于您的DNS)https://example..com
是有效URL,与上面的相同#3 楼
function isURL(str) {
var pattern = new RegExp('^(https?:\/\/)?'+ // protocol
'((([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 locator
return pattern.test(str);
}
评论
google搜索图像链接失败:http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&docid=nIv5rk2GyP3hXM&tbnid=isiOkMe3nCtexM:&ved=0CAUQjRw&url=http%3A%2Fwiki2 .com%2Fwiki%2FLion&ei = ygZXU_2fGKbMsQTf4YLgAQ&bvm = bv.65177938,d.aWc&psig = AFQjCNEpBfKnal9kU7Zu4n7RnEt2nerN4g&ust = 1398298682009707
– Bill davis
14-4-23在0:23
这是无法使用的慢
–埃尔南·埃切(HernánEche)
15年1月28日在3:00
@HernánEche你这么慢是什么意思?开始=新的Date(); isURL(“ http://michalstefanow.com”);结束=新的Date(); diff =结束-开始; console.log(diff)我放了水壶,上了厕所,叫我妈妈,事情很快就完成了...
–火星罗伯逊
16年5月2日在13:59
对于aaa,它返回true。
–alex naumov
16年1月1日在9:13
这绝对不是正确的答案。它无法通过许多测试用例,更重要的是,它甚至会使页面挂在短字符串上:isURL('12345678901234567890123')添加更多字符,甚至更糟。
–aaaamarks
18年4月16日在16:51
#4 楼
建议不要使用正则表达式,而建议使用锚元素。设置
href
的anchor
属性时,将设置其他各种属性。 var parser = document.createElement('a');
parser.href = "http://example.com:3000/pathname/?search=test#hash";
parser.protocol; // => "http:"
parser.hostname; // => "example.com"
parser.port; // => "3000"
parser.pathname; // => "/pathname/"
parser.search; // => "?search=test"
parser.hash; // => "#hash"
parser.host; // => "example.com:3000"
源
但是,如果绑定到
href
的值不是有效的网址,则这些辅助属性的值将空字符串。编辑:如注释中所指出:如果使用无效的url,则可以替换当前URL的属性。
因此,只要由于您没有传递当前页面的URL,因此可以执行以下操作:
function isValidURL(str) {
var a = document.createElement('a');
a.href = str;
return (a.host && a.host != window.location.host);
}
评论
并非如此(至少在Chrome 48中如此)。如果传递给a.href的网址无效,则parser.host返回您当前所在页面的主机名,而不是预期的false。
–山姆·贝克汉姆
16-2-25在15:37
加!那真是怪了。我发誓我已经测试过了!我认为可以说确实不需要在当前页面上使用,因此可以更改条件。我将编辑帖子。
–卢克
16年2月25日在22:48
这不是一个非常典型的用例,但是此技术在Firefox浏览器窗口的上下文中不起作用(对于插件开发很重要)
–chrmod
16年5月15日在16:01
函数isValidURL(str):比使用正则表达式好得多!谢谢!
–罗德里戈
18年4月13日在15:55
解决问题的非常简单的方法。这些属性是实验性的:developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
– Boris D. Teoharov
18年11月30日在14:19
#5 楼
我正在使用以下功能来验证是否带有http/https
的URL: function isValidURL(string) {
var res = string.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g);
return (res !== null)
};
var testCase1 = "http://en.wikipedia.org/wiki/Procter_&_Gamble";
console.log(isValidURL(testCase1)); // return true
var testCase2 = "http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&docid=nIv5rk2GyP3hXM&tbnid=isiOkMe3nCtexM:&ved=0CAUQjRw&url=http%3A%2F%2Fanimalcrossing.wikia.com%2Fwiki%2FLion&ei=ygZXU_2fGKbMsQTf4YLgAQ&bvm=bv.65177938,d.aWc&psig=AFQjCNEpBfKnal9kU7Zu4n7RnEt2nerN4g&ust=1398298682009707";
console.log(isValidURL(testCase2)); // return true
var testCase3 = "https://sdfasd";
console.log(isValidURL(testCase3)); // return false
var testCase4 = "dfdsfdsfdfdsfsdfs";
console.log(isValidURL(testCase4)); // return false
var testCase5 = "magnet:?xt=urn:btih:123";
console.log(isValidURL(testCase5)); // return false
var testCase6 = "https://stackoverflow.com/";
console.log(isValidURL(testCase6)); // return true
var testCase7 = "https://w";
console.log(isValidURL(testCase7)); // return false
var testCase8 = "https://sdfasdp.ppppppppppp";
console.log(isValidURL(testCase8)); // return false
评论
似乎是一个不错的解决方案!您能否添加一些测试来证明它在某些极端情况下仍然有效(例如,请参见这些注释)?
–巴吉
18年4月16日在7:36
@Basj添加了测试用例。请检查
– Vikasdeep Singh
18年4月16日在8:00
不错,不能通过http://⌘.ws或142.42.1.1,并且允许http://.www.foo.bar./,但它不会像其他正则表达式一样挂起,包括评分最高的答案。
–aaaamarks
18年4月16日在15:58
@aamarks我检查了您的答案。您的答案因https://sdfasdp.ppppppppppppp而失败,即返回true,但我的返回false,这是我想的。
– Vikasdeep Singh
18年4月17日在2:23
它返回sandf@gmail.com的true ...应该吗?我想应该不会
–佐伊卜·阿里(Zohaib Ali)
19年1月2日,9:05
#6 楼
使用JavaScript验证网址如下所示。function ValidURL(str) {
var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
if(!regex .test(str)) {
alert("Please enter valid URL.");
return false;
} else {
return true;
}
}
评论
正则表达式的几个部分可以大大减少:a)(http | https)为(?:https?); b):{0,1}到:?; c)[0-9]至\ d
– Dima Parzhitsky
17 Mar 28 '17 at 14:52
#7 楼
依赖库:https://www.npmjs.com/package/valid-url
import { isWebUri } from 'valid-url';
// ...
if (!isWebUri(url)) {
return "Not a valid url.";
}
评论
这给我给浏览器实际解析的怪异网址带来了很多麻烦,例如:网址中包含{
– Willyfrog
20年6月19日在8:56
#8 楼
改进可接受的答案...检查ftp / ftps是否作为协议
双重转义反斜杠(\\)
确保域中有一个点和扩展名(.com .io .xyz)
允许在路径中使用完整的冒号(:),例如http://thingiverse.com/download:1894343
允许在路径中使用&号,例如http://en.wikipedia.org/wiki/Procter_&_Gamble
在路径中允许@符号,例如https://medium.com/@techytimo
isURL(str) {
var pattern = new RegExp('^((ft|htt)ps?:\/\/)?'+ // protocol
'((([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|'+ // domain name and extension
'((\d{1,3}\.){3}\d{1,3}))'+ // OR ip (v4) address
'(\:\d+)?'+ // port
'(\/[-a-z\d%@_.~+&:]*)*'+ // path
'(\?[;&a-z\d%@_.,~+&:=-]*)?'+ // query string
'(\#[-a-z\d_]*)?$','i'); // fragment locator
return pattern.test(str);
}
评论
不,它不应该是公认的答案。像其他一些字符串一样,它仅停留在33个字符串上:isURL('123456789012345678901234567890123')并在许多边缘案例测试中失败:foo.com/blah_blah_(wikipedia)_(再次)//错误地返回false。
–aaaamarks
18年4月16日在16:23
那是因为localhost:8080不是有效的URL。
– Shane
18-10-12在18:56
工作示例:runkit.com/shanekenyon87/5bc0e57263c77b0012db05dc
– Shane
18-10-12在19:07
应该是ftps:// localhost:8080 =)
–vp_arth
19年2月10日在21:22
它似乎不起作用:挂在长输入上(如@aanmarks所说)
–cecemel
19年3月28日在16:50
#9 楼
这是另一种方法。 var elm;
function isValidURL(u){
if(!elm){
elm = document.createElement('input');
elm.setAttribute('type', 'url');
}
elm.value = u;
return elm.validity.valid;
}
console.log(isValidURL('http://www.google.com/'));
console.log(isValidURL('//google.com'));
console.log(isValidURL('google.com'));
console.log(isValidURL('localhost:8000'));
评论
教育法规!这里的机制可能与Pavlo代码中新URL(string)的工作方式相同。两种测试在我测试的所有边缘情况下均具有相同的结果。我喜欢他的代码,因为它更简单并且不涉及创建元素,但是您的代码却快了好几倍(可能是因为它在第一次使用后没有创建el)。
–aaaamarks
18年4月23日在22:05
谢谢!我执行了您的建议。但是请注意:较旧的浏览器和/或移动设备WebView可能未实现元素。因此,输入值将像普通文本一样对待(不进行URL验证)。 REF:developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input/url
–帕尼尼午餐者
18/12/7在15:17
#10 楼
(我没有代表对ValidURL示例进行评论;因此,将其作为答案。)有时。要使用正则表达式验证此类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。
评论
我认为起初这很好,但是它在mathiasbynens.be/demo/url-regex上的许多测试中均未通过,然后挂在isValidURL(“ https://d1f4470da51b49289906b3d6cbd65074@app.getsentry.com/13176”)
–aaaamarks
18年4月23日在21:21
是的,就像我说的那样,我只是对协议部分进行了评论。我添加了身份验证子句来处理@。它没有挂在我的浏览器中。
–科拉
18-4-25的3:23
抱歉,我正在对其中的几个进行评估,却错过了您的评论给定答案。我认为您的修正甚至在我第一次访问此页面时帮助我开始了这些工作。现在不挂。
–aaaamarks
18年4月25日在4:42
#11 楼
您可以使用URL本机API: const isUrl = string => {
try { return Boolean(new URL(string)); }
catch(e){ return false; }
}
评论
看起来与@pavlo提供的答案非常相似,只是变量名称已更改;)
–慕尼蒙娜(Munim Munna)
18年4月16日在21:28
到目前为止,确实应该有一个简单的本机方法来检查此问题-这个答案看起来很有希望,但早在上述@Basj时就返回了true。
– zero_cool
'18 Sep 6'在6:11
#12 楼
如前所述,完美的正则表达式是难以捉摸的,但似乎仍然是一种合理的方法(替代方法是服务器端测试或新的实验性URL API)。但是,对于常见的URL,排名靠前的答案通常会返回false,但更糟糕的是,即使是像isURL('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
这样的简单字符串,它也会冻结您的应用程序/页面几分钟。一些评论中已经指出了这一点,但是很可能并没有输入不好的值来查看它。这样的挂起使该代码无法在任何严肃的应用程序中使用。我认为这是由于在类似((([a-z\d]([a-z\d-]*[a-z\d])*)\.?)+[a-z]{2,}|' ...
的代码中重复出现了不区分大小写的集合。取出“ i”,它不会挂起,但是当然不能按预期工作。但是,即使使用了忽略大小写标志,那些测试也会拒绝允许的高unicode值。已经提到的最好的是:来自Github segmentio / is-url。关于代码存储库的好处是,您可以看到测试和任何问题,以及贯穿其中的测试字符串。有一个分支将允许字符串缺少协议,例如
google.com
,尽管那时您可能做过多的假设。存储库已更新,我不打算尝试在此处保留镜像。为了避免RegEx重做可被DOS攻击利用,已将其分为多个测试(我不必担心客户端JS会担心这一点,但是您确实需要担心页面挂了这么长时间以至访问者离开了您的网站。)我见过另外一个存储库,它可能在dperini / regex-weburl.js中对isURL可能更好,但是它非常复杂。它具有更大的有效和无效URL测试列表。上面简单的一个仍然可以传递所有正数,并且只能阻止一些奇怪的负数,例如
http://a.b--c.de/
以及特殊的ips。使用浏览器的“开发人员工具”检查器对dperini / regex-weburl.js进行测试。function isURL(str) {
return /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(str);
}
,然后测试'a's的字符串。
评论
我检查了你的答案。您的答案因sdfasdp.ppppppppppppp而失败,即返回true但预期为false
– Vikasdeep Singh
18年4月17日在8:26
从结构上来说,我认为这是一个有效的URL。不是标准专家,但我认为.com部分的长度没有限制(我知道.online是合法的)。
–aaaamarks
18年4月17日在22:12
几个月前,我几乎不知道如何编写正则表达式。问题很严重。我引用的两个正则表达式都可以完成isURL('a'.repeat(100))数百万次/秒(dperini中更复杂的一个实际上更快)。形式([a-zA-Z] +)*的某些高级答案可能需要几个小时才能完成一次。查找RegEx重做以获取更多信息。
–aaaamarks
18-4-23在20:27
#13 楼
我无法评论离#5717133最近的帖子,但是下面是我弄清楚如何使@ tom-gullen regex工作的方式。/^(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
评论
这对我有用,但是我需要反斜杠。 var pattern = new RegExp('((https?:\\ / \\ //)?((([[az \\ d]([az \\ d-] * [az \\ d])*)\\。) + [az] {2,} |((\\ d {1,3} \\。){3} \\ d {1,3}))((\\:\\ d +)?(\\ / [ -az \\ d%_。〜+] *)*(\\?[;&a-z \\ d%_。〜+ =-] *)?(\\#[-az \\ d _] *) $','i');
–费尔南多·查韦斯·埃雷拉(Fernando Chavez Herrera)
16年6月20日在21:29
检查w3resource.com/javascript-exercises/…了解更多测试用例
– Kewal Shah
20年5月7日在8:33
#14 楼
我一直用来验证URL“字符串”的一个函数是:示例:
var matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;
function isUrl(string){
return matcher.test(string);
}
#15 楼
使用validateator.jsES6
import isURL from 'validator/lib/isURL'
isURL(string)
没有ES6
var validator = require('validator');
validator.isURL(string)
您还可以通过传递可选的
options
对象作为isURL
的第二个参数来微调此函数的行为这是默认的
options
对象:let options = {
protocols: [
'http',
'https',
'ftp'
],
require_tld: true,
require_protocol: false,
require_host: true,
require_valid_protocol: true,
allow_underscores: false,
host_whitelist: false,
host_blacklist: false,
allow_trailing_dot: false,
allow_protocol_relative_urls: false,
disallow_auth: false
}
isURL(string, options)
host_whitelist
和host_blacklist
可以是主机阵列。它们还支持正则表达式。let options = {
host_blacklist: ['foo.com', 'bar.com'],
}
isURL('http://foobar.com', options) // => true
isURL('http://foo.bar.com/', options) // => true
isURL('http://qux.com', options) // => true
isURL('http://bar.com/', options) // => false
isURL('http://foo.com/', options) // => false
options = {
host_blacklist: ['bar.com', 'foo.com', /\.foo\.com$/],
}
isURL('http://foobar.com', options) // => true
isURL('http://foo.bar.com/', options) // => true
isURL('http://qux.com', options) // => true
isURL('http://bar.com/', options) // => false
isURL('http://foo.com/', options) // => false
isURL('http://images.foo.com/', options) // => false
isURL('http://cdn.foo.com/', options) // => false
isURL('http://a.b.c.foo.com/', options) // => false
评论
真好!小型库(最小库少于4万个),流行库(npm每周下载量超过3M),为您指定特定用例的URL有效性提供了极大的灵活性,除URL外还具有许多其他验证器。到目前为止,这是最好的答案,恕我直言。
–贾维德·贾梅(Javid Jamae)
20-3-26在2:07
不错的图书馆。它不仅可以验证URL,还可以验证许多其他内容。
–贝米佩菲
20/12/2在11:09
#16 楼
使用纯正则表达式很难做到这一点,因为URL有很多“不便”。例如域名对连字符的限制很复杂: >一个。中间可以有许多连续的连字符。
b。但是域名的第一个字符和最后一个字符不能为连字符
c。第3个字符和第4个字符不能都是连字符
同样,端口号只能在1-65535范围内。如果您提取端口部分并转换为
int
,这很容易检查,但是使用正则表达式很难检查。也没有简单的方法来检查有效的域扩展名。一些国家/地区具有二级域名(例如'co.uk'),或者扩展名可以是一个长词,例如'.international'。并定期添加新的TLD。此类内容只能通过硬编码列表进行检查。 (请参阅https://en.wikipedia.org/wiki/Top-level_domain)
然后有磁铁URL,FTP地址等。这些都有不同的要求。不过,这里是该函数可处理几乎所有内容,但以下情况除外:
情况1。c
接受任何1-5位数字的端口号
接受任何扩展名2-13个字符
不接受ftp,磁铁等...
function isValidURL(input) {
pattern = '^(https?:\/\/)?' + // protocol
'((([a-zA-Z\d]([a-zA-Z\d-]{0,61}[a-zA-Z\d])*\.)+' + // sub-domain + domain name
'[a-zA-Z]{2,13})' + // extension
'|((\d{1,3}\.){3}\d{1,3})' + // OR ip (v4) address
'|localhost)' + // OR localhost
'(\:\d{1,5})?' + // port
'(\/[a-zA-Z\&\d%_.~+-:@]*)*' + // path
'(\?[a-zA-Z\&\d%_.,~+-:@=;&]*)?' + // query string
'(\#[-a-zA-Z&\d_]*)?$'; // fragment locator
regex = new RegExp(pattern);
return regex.test(input);
}
let tests = [];
tests.push(['', false]);
tests.push(['http://en.wikipedia.org/wiki/Procter_&_Gamble', true]);
tests.push(['https://sdfasd', false]);
tests.push(['http://www.google.com/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&docid=nIv5rk2GyP3hXM&tbnid=isiOkMe3nCtexM:&ved=0CAUQjRw&url=http%3A%2F%2Fanimalcrossing.wikia.com%2Fwiki%2FLion&ei=ygZXU_2fGKbMsQTf4YLgAQ&bvm=bv.65177938,d.aWc&psig=AFQjCNEpBfKnal9kU7Zu4n7RnEt2nerN4g&ust=1398298682009707', true]);
tests.push(['https://stackoverflow.com/', true]);
tests.push(['https://w', false]);
tests.push(['aaa', false]);
tests.push(['aaaa', false]);
tests.push(['oh.my', true]);
tests.push(['dfdsfdsfdfdsfsdfs', false]);
tests.push(['google.co.uk', true]);
tests.push(['test-domain.MUSEUM', true]);
tests.push(['-hyphen-start.gov.tr', false]);
tests.push(['hyphen-end-.com', false]);
tests.push(['https://sdfasdp.international', true]);
tests.push(['https://sdfasdp.pppppppp', false]);
tests.push(['https://sdfasdp.ppppppppppppppppppp', false]);
tests.push(['https://sdfasd', false]);
tests.push(['https://sub1.1234.sub3.sub4.sub5.co.uk/?', true]);
tests.push(['http://www.google-com.123', false]);
tests.push(['http://my--testdomain.com', false]);
tests.push(['http://my2nd--testdomain.com', true]);
tests.push(['http://thingiverse.com/download:1894343', true]);
tests.push(['https://medium.com/@techytimo', true]);
tests.push(['http://localhost', true]);
tests.push(['localhost', true]);
tests.push(['localhost:8080', true]);
tests.push(['localhost:65536', true]);
tests.push(['localhost:80000', false]);
tests.push(['magnet:?xt=urn:btih:123', true]);
for (let i = 0; i < tests.length; i++) {
console.log('Test #' + i + (isValidURL(tests[i][0]) == tests[i][1] ? ' passed' : ' failed') + ' on ["' + tests[i][0] + '", ' + tests[i][1] + ']');
}
#17 楼
此功能禁止本地主机,并且仅允许网页URL(即,仅允许http或https协议)。也仅允许此处定义的安全字符:https://www.urlencoder.io/learn/
function isValidWebUrl(url) {
let regEx = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/gm;
return regEx.test(url);
}
#18 楼
与我一起工作function isURL(str) {
var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/;
var pattern = new RegExp(regex);
return pattern.test(str);
}
评论
答案已经在4年前由kavitha Reddy给出。
–aaaamarks
19年6月1日在19:09
我只是让它变得更加简单和抽象
– HeshamSalama
20-2-20在13:15
#19 楼
如果可以更改输入类型,我认为此解决方案会更容易: :your.html
<input id="foo" type="url">
your.js
// The selector is JQuery, but the function is plain JS
$("#foo").on("keyup", function() {
if (this.checkValidity()) {
// The url is valid
} else {
// The url is invalid
}
});
#20 楼
已经有很多答案,但是这是另外一个贡献: > URL
源
#21 楼
我认为使用本地URL API优于@pavlo建议的复杂正则表达式模式。它有一些缺点,但是我们可以通过一些额外的代码来解决。对于以下有效的网址,此方法将失败。//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;
}
}
hostname
属性是javascript:void(0)
的空字符串,因此它也可以使用,也可以添加IP地址验证器。我最想坚持使用本机API,并希望它会在不久的将来开始支持所有功能。 评论
有趣,但可能仍需要对正则表达式进行处理,因为它现在引入了假阴性,而在我完成的测试中没有新的URL。这是在调用:http://142.42.1.1 // false并阻止高unicode字符串。
–aaaamarks
18年4月23日在22:17
#22 楼
该问题询问一种验证方法,以获取诸如stackoverflow
之类的URL,而协议中没有主机名或任何点。因此,验证URL sintax不是问题,而是通过实际调用它来检查它是否为有效URL。我尝试了几种方法来了解该URL是否存在并且可以从浏览器中调用,但没有找到任何方法来使用javascript测试调用的响应标头:
添加锚元素可以触发
click()
方法。 用
'GET'
对具有挑战性的url进行ajax调用是可以的,但是由于CORS
的策略,它具有各种局限性,而不是使用ajax
,因为url可能在我服务器的域之外。使用fetch API的解决方法类似于ajax。另一个问题是我的服务器处于
https
协议下,并且在调用非安全url时引发异常。可以想到正在获取一些使用javascript尝试执行CURL
之类的工具来执行curl -I <url>
的工具。不幸的是,我没有找到任何东西,而且不可能。我将不胜感激对此的任何评论。但是,最后,我有一台运行PHP
的服务器,并且由于几乎所有请求都使用Ajax,因此我在服务器端编写了一个函数来执行在那里卷曲请求并返回浏览器。 关于“ stackoverflow”问题上的单个网址,它将带我到
https://daniserver.com.ar/stackoverflow
,其中daniserver.com.ar是我自己的域名。 评论
OP可能已经表明了他的意图。当然,这个问题会因您的需要而异,排除误报还是包括误报更重要。正如问题所述,我似乎没有任何答案。您真的可以接受foo并假设它是http或https或.com或.es或不计其数的后缀吗?您是否一直向厨房扔水槽,直到获得真实的水准?
–aaaamarks
18年4月23日在21:45
#23 楼
这似乎是CS中最困难的问题之一;)这是另一个不完整的解决方案,对我来说效果很好,而且比我在这里看到的其他解决方案要好。我为此使用input [type = url]来支持IE11,否则使用window.URL来执行验证会更简单:
const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
function isValidIpv4(ip) {
if (!ipv4Regex.test(ip)) return false;
return !ip.split('.').find(n => n > 255);
}
const domainRegex = /(?:[a-z0-9-]{1,63}\.){1,125}[a-z]{2,63}$/i;
function isValidDomain(domain) {
return isValidIpv4(domain) || domainRegex.test(domain);
}
let input;
function validateUrl(url) {
if (! /^https?:\/\//.test(url)) url = `http://${url}`; // assuming Babel is used
// to support IE11 we'll resort to input[type=url] instead of window.URL:
// try { return isValidDomain(new URL(url).host) && url; } catch(e) { return false; }
if (!input) { input = document.createElement('input'); input.type = 'url'; }
input.value = url;
if (! input.validity.valid) return false;
const domain = url.split(/^https?:\/\//)[1].split('/')[0].split('@').pop();
return isValidDomain(domain) && url;
}
console.log(validateUrl('google'), // false
validateUrl('user:pw@mydomain.com'),
validateUrl('https://google.com'),
validateUrl('100.100.100.100/abc'),
validateUrl('100.100.100.256/abc')); // false
为了接受不完整的输入(例如“ www.mydomain.com”),如果在这些情况下协议为“ http”,它也会使其有效,如果地址有效。
它还支持IPv4域,但不支持IPv6。
#24 楼
在我的情况下,我唯一的要求是,将用户输入放置在标签的href中时,用户输入不会被解释为相对链接,并且此处的答案要么是OTT,要么是所允许的URL不符合我的要求,因此我要使用的是:^https?://.+$
不用正则表达式就可以很容易地实现相同的事情。
#25 楼
显然,这不是最有效的方法,但是它易于阅读,并且易于形成您所需的任何内容。从这里添加正则表达式/复杂性会更容易。所以这是一种非常实用的方法const validFirstBits = ["ftp://", "http://", "https://", "www."];
const invalidPatterns = [" ", "//.", ".."];
export function isUrl(word) {
// less than www.1.dk
if (!word || word.length < 8) return false;
// Let's check and see, if our candidate starts with some of our valid first bits
const firstBitIsValid = validFirstBits.some(bit => word.indexOf(bit) === 0);
if (!firstBitIsValid) return false;
const hasInvalidPatterns = invalidPatterns.some(
pattern => word.indexOf(pattern) !== -1,
);
if (hasInvalidPatterns) return false;
const dotSplit = word.split(".");
if (dotSplit.length > 1) {
const lastBit = dotSplit.pop(); // string or undefined
if (!lastBit) return false;
const length = lastBit.length;
const lastBitIsValid =
length > 1 || (length === 1 && !isNaN(parseInt(lastBit)));
return !!lastBitIsValid;
}
return false;
}
测试:
import { isUrl } from "./foo";
describe("Foo", () => {
test("should validate correct urls correctly", function() {
const validUrls = [
"http://example.com",
"http://example.com/blah",
"http://127.0.0.1",
"http://127.0.0.1/wow",
"https://example.com",
"https://example.com/blah",
"https://127.0.0.1:1234",
"ftp://example.com",
"ftp://example.com/blah",
"ftp://127.0.0.1",
"www.example.com",
"www.example.com/blah",
];
validUrls.forEach(url => {
expect(isUrl(url) && url).toEqual(url);
});
});
test("should validate invalid urls correctly", function() {
const inValidUrls = [
"http:// foo.com",
"http:/foo.com",
"http://.foo.com",
"http://foo..com",
"http://.com",
"http://foo",
"http://foo.c",
];
inValidUrls.forEach(url => {
expect(!isUrl(url) && url).toEqual(url);
});
});
});
#26 楼
Mathias Bynens已编译了带有测试URL的知名URL正则表达式列表。没有什么理由写一个新的正则表达式。只需选择一个最适合您的现有正则表达式即可。 Bynens列表中的所有正则表达式都会产生误报和误报。我建议您使用现有的URL解析器(例如JavaScript中的
new URL('http://www.example.com/')
),然后对要执行的检查应用检查URL解析和标准化形式。它的组件。使用JavaScript URL
接口还有一个额外的好处,就是它只接受浏览器真正接受的此类URL。例如http://w_w_w.example.com/
,http://www..example.com/
,http://123.example.com/
都具有无效的主机名部分,但是我知道的每个浏览器都将尝试打开它们而不会引起投诉,并且当您在/etc/hosts/
中为这些无效名称指定IP地址时,此类URL甚至可以在您的计算机上使用。 br /> 因此,问题不仅仅在于URL是否有效,而在于在特定的上下文中哪些URL可以工作并且应该被允许。
如果您想做URL验证中有许多容易忽略的细节和极端情况:
URL可能包含
http://user:password@www.example.com/
中的凭据。端口号必须在0-范围内65535,但是您可能仍要排除通配符端口0。
端口号可能带有前导零,如http://www.example.com:000080/。IPv4地址决不限于0-255范围内的4个十进制整数。您可以使用1-4个整数,它们可以是十进制,八进制或十六进制。 URL https://010.010.000010.010/、https://0x8.0x8.0x0008.0x8/、https://8.8.2056/、https://8.526344/、https:// 134744072 /只是一种新颖的https://8.8.8.8/编写方式。
允许环回地址(http://127.0.0.1/),私有IP地址(http://192.168.1.1),本地链接地址( http://169.254.100.200)等可能会对安全性或隐私产生影响。例如,如果您允许他们作为论坛中用户头像的地址,则会导致用户的浏览器在其本地网络和物联网中发送未经请求的网络请求,此类请求可能会导致有趣而又不太有趣的事情。
出于相同的原因,您可能希望放弃指向不完全合格的主机名的链接,换句话说,就是没有点的主机名。 )。
链接的主机名部分可能包含IPv6地址的尖括号,如http:// [:: 1]。
IPv6地址也具有专用网络或链接本地地址等的范围。
/>如果您阻止某些IPv4地址,请记住,例如https://127.0.0.1和https:// [:: ffff:127.0.0.1]指向同一资源(如果您的计算机的回送设备是URL的主机名部分现在可能包含Unicode,因此字符范围
http://www.stackoverflow.com.
绝对不再足够。许多顶级域的注册表都定义了特定的限制,例如在允许的范围内。 Unicode字符集。或它们再细分其名称空间(如
[-0-9a-zA-z]
和许多其他名称空间)。 >Unicode顶级域(及其带有“ xn--”的punycode编码)仍必须仅包含字母,但谁想在正则表达式中进行检查?这些限制和规则适用于哪些项目需求和品味。
我最近写了一个Web应用程序的URL验证器,适用于论坛,社交网络等中用户提供的URL。随意将其用作自己的基础:
JavaScript / Typescript版本((角)前端)
Perl版本后端
我还写了一篇博客文章《 URL验证的可怕细节》,其中包含更深入的信息。
#27 楼
我将函数更改为Match +,并在此处使用斜杠及其工作进行更改:(http://和https)都#28 楼
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');
那有人说,我不确定是否存在禁止在查询字符串或哈希中使用
@
的白皮书规则。#29 楼
这只是一个非常简单的检查,以确保存在有效的协议,并且域扩展名必须是两个或更多字符。is_valid_url = ( $url ) => {
let $url_object = null;
try {
$url_object = new URL( $url );
} catch ( $error ) {
return false;
}
const $protocol = $url_object.protocol;
const $protocol_position = $url.lastIndexOf( $protocol );
const $domain_extension_position = $url.lastIndexOf( '.' );
return (
$protocol_position === 0 &&
[ 'http:', 'https:' ].indexOf( $protocol ) !== - 1 &&
$domain_extension_position > 2 && $url.length - $domain_extension_position > 2
);
};
#30 楼
如果还需要支持https://localhost:3000
,请使用此[Devshed]正则表达式的修改版本。 function isURL(url) {
if(!url) return false;
var pattern = new RegExp('^(https?:\/\/)?'+ // protocol
'((([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
'localhost' + // OR localhost
'(\:\d+)?(\/[-a-z\d%_.~+]*)*'+ // port and path
'(\?[;&a-z\d%_.~+=-]*)?'+ // query string
'(\#[-a-z\d_]*)?$', 'i'); // fragment locator
return pattern.test(url);
}
评论
如果缺少http,则默认情况下没有网址。@nfechner就是说,如果它没有指定协议并使用冒号字符(最好是下一个正斜杠),那么它不是URL吗?
正如您可以在URL RFC中阅读的那样,使String成为有效URL的实际上唯一必要的部分是冒号。有效URL如下:
请参阅stackoverflow.com/a/3975573/572180
如何测试某物是否为URL高度依赖于上下文,并且如果没有进一步的限定,也太含糊。它对您是否重要是否符合URL RFC规范,在OS系统调用中打开URL时是否起作用,在锚元素中解析为href,在调用window.open(url)时起作用,指向真正是否存在,可以在浏览器的位置栏中使用,还是以上两者的组合?根据您关心的答案,您将获得截然不同的答案。