在JavaScript中是否有一种方法来检查字符串是否是URL?
regex被排除在外,因为URL很可能写成stackoverflow;也就是说,它可能没有。com, WWW或http。
在JavaScript中是否有一种方法来检查字符串是否是URL?
regex被排除在外,因为URL很可能写成stackoverflow;也就是说,它可能没有。com, WWW或http。
当前回答
在我的情况下,我唯一的要求是,用户输入不会被解释为一个相对链接时,放置在一个标签的href和这里的答案要么有点OTT,要么允许url不符合我的要求,所以这就是我要做的:
^https?://.+$
没有正则表达式,同样的事情也可以很容易地实现。
其他回答
我建议使用锚元素,而不是使用正则表达式。
当你设置一个锚的href属性时,其他各种属性也会被设置。
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的属性。
所以,只要你没有传递当前页面的URL,你可以这样做:
function isValidURL(str) {
var a = document.createElement('a');
a.href = str;
return (a.host && a.host != window.location.host);
}
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');
话虽如此,我不确定是否有白皮书规则禁止在查询字符串或哈希中使用@。
对已接受答案的改进…
Check for ftp/ftps as protocol Has double escaping for backslashes (\\) Ensures that domains have a dot and an extension (.com .io .xyz) Allows full colon (:) in the path e.g. http://thingiverse.com/download:1894343 Allows ampersand (&) in path e.g http://en.wikipedia.org/wiki/Procter_&_Gamble Allows @ symbol in path e.g. 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); }
As has been noted the perfect regex is elusive but still seems to be a reasonable approach (alternatives are server side tests or the new experimental URL API). However the high ranking answers are often returning false for common URLs but even worse will freeze your app/page for minutes on even as simple a string as isURL('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'). It's been pointed out in some of the comments, but most probably haven't entered a bad value to see it. Hanging like that makes that code unusable in any serious application. I think it's due to the repeated case insensitive sets in code like ((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|' .... Take out the 'i' and it doesn't hang but will of course not work as desired. But even with the ignore case flag those tests reject high unicode values that are allowed.
已经提到的最好的是:
function isURL(str) {
return /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/.test(str);
}
That comes from Github segmentio/is-url. The good thing about a code repository is you can see the testing and any issues and also the test strings run through it. There's a branch that would allow strings missing protocol like google.com, though you're probably making too many assumptions then. The repository has been updated and I'm not planning on trying to keep up a mirror here. It's been broken up into separate tests to avoid RegEx redos which can be exploited for DOS attacks (I don't think you have to worry about that with client side js, but you do have to worry about your page hanging for so long that your visitor leaves your site).
在dperini/regex- webburl .js中,我还看到过另一个存储库,它可能更适合isURL,但它非常复杂。它有一个更大的有效和无效url的测试列表。上面的简单的一个仍然通过了所有的正面信息,只有一些奇怪的负面信息,如http://a.b--c.de/以及特殊的ip。
无论你选择哪一个,在使用浏览器的开发人员工具检查器时,通过这个函数运行它,这个函数是我从dperini/regex- webburl .js上的测试中改编的。
function testIsURL() {
//should match
console.assert(isURL("http://foo.com/blah_blah"));
console.assert(isURL("http://foo.com/blah_blah/"));
console.assert(isURL("http://foo.com/blah_blah_(wikipedia)"));
console.assert(isURL("http://foo.com/blah_blah_(wikipedia)_(again)"));
console.assert(isURL("http://www.example.com/wpstyle/?p=364"));
console.assert(isURL("https://www.example.com/foo/?bar=baz&inga=42&quux"));
console.assert(isURL("http://✪df.ws/123"));
console.assert(isURL("http://userid:password@example.com:8080"));
console.assert(isURL("http://userid:password@example.com:8080/"));
console.assert(isURL("http://userid@example.com"));
console.assert(isURL("http://userid@example.com/"));
console.assert(isURL("http://userid@example.com:8080"));
console.assert(isURL("http://userid@example.com:8080/"));
console.assert(isURL("http://userid:password@example.com"));
console.assert(isURL("http://userid:password@example.com/"));
console.assert(isURL("http://142.42.1.1/"));
console.assert(isURL("http://142.42.1.1:8080/"));
console.assert(isURL("http://➡.ws/䨹"));
console.assert(isURL("http://⌘.ws"));
console.assert(isURL("http://⌘.ws/"));
console.assert(isURL("http://foo.com/blah_(wikipedia)#cite-1"));
console.assert(isURL("http://foo.com/blah_(wikipedia)_blah#cite-1"));
console.assert(isURL("http://foo.com/unicode_(✪)_in_parens"));
console.assert(isURL("http://foo.com/(something)?after=parens"));
console.assert(isURL("http://☺.damowmow.com/"));
console.assert(isURL("http://code.google.com/events/#&product=browser"));
console.assert(isURL("http://j.mp"));
console.assert(isURL("ftp://foo.bar/baz"));
console.assert(isURL("http://foo.bar/?q=Test%20URL-encoded%20stuff"));
console.assert(isURL("http://مثال.إختبار"));
console.assert(isURL("http://例子.测试"));
console.assert(isURL("http://उदाहरण.परीक्षा"));
console.assert(isURL("http://-.~_!$&'()*+,;=:%40:80%2f::::::@example.com"));
console.assert(isURL("http://1337.net"));
console.assert(isURL("http://a.b-c.de"));
console.assert(isURL("http://223.255.255.254"));
console.assert(isURL("postgres://u:p@example.com:5702/db"));
console.assert(isURL("https://d1f4470da51b49289906b3d6cbd65074@app.getsentry.com/13176"));
//SHOULD NOT MATCH:
console.assert(!isURL("http://"));
console.assert(!isURL("http://."));
console.assert(!isURL("http://.."));
console.assert(!isURL("http://../"));
console.assert(!isURL("http://?"));
console.assert(!isURL("http://??"));
console.assert(!isURL("http://??/"));
console.assert(!isURL("http://#"));
console.assert(!isURL("http://##"));
console.assert(!isURL("http://##/"));
console.assert(!isURL("http://foo.bar?q=Spaces should be encoded"));
console.assert(!isURL("//"));
console.assert(!isURL("//a"));
console.assert(!isURL("///a"));
console.assert(!isURL("///"));
console.assert(!isURL("http:///a"));
console.assert(!isURL("foo.com"));
console.assert(!isURL("rdar://1234"));
console.assert(!isURL("h://test"));
console.assert(!isURL("http:// shouldfail.com"));
console.assert(!isURL(":// should fail"));
console.assert(!isURL("http://foo.bar/foo(bar)baz quux"));
console.assert(!isURL("ftps://foo.bar/"));
console.assert(!isURL("http://-error-.invalid/"));
console.assert(!isURL("http://a.b--c.de/"));
console.assert(!isURL("http://-a.b.co"));
console.assert(!isURL("http://a.b-.co"));
console.assert(!isURL("http://0.0.0.0"));
console.assert(!isURL("http://10.1.1.0"));
console.assert(!isURL("http://10.1.1.255"));
console.assert(!isURL("http://224.1.1.1"));
console.assert(!isURL("http://1.1.1.1.1"));
console.assert(!isURL("http://123.123.123"));
console.assert(!isURL("http://3628126748"));
console.assert(!isURL("http://.www.foo.bar/"));
console.assert(!isURL("http://www.foo.bar./"));
console.assert(!isURL("http://.www.foo.bar./"));
console.assert(!isURL("http://10.1.1.1"));}
然后测试这串a。
在你发布一个看起来很棒的正则表达式之前,看看Mathias Bynens对isURL正则表达式的比较,了解更多信息。
这里只是一个非常简单的检查,以确保有一个有效的协议,并且域扩展名必须是两个或更多字符。
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
);
};