如何检查给定的字符串是否是有效的URL地址?
我对正则表达式的知识是基本的,不允许我从我已经在网上看到的数百个正则表达式中进行选择。
如何检查给定的字符串是否是有效的URL地址?
我对正则表达式的知识是基本的,不允许我从我已经在网上看到的数百个正则表达式中进行选择。
当前回答
关于眼睑问题,他的回答是“这是基于我对URI规范的阅读。”谢谢眼睑,你的是我寻求的完美的解决方案,因为它是基于URI规范!出色的工作。:)
我不得不做了两个修改。第一个在PHP (v5.2.10)中使用preg_match()函数使regexp正确匹配IP地址url的方法。
我不得不在管道周围的“IP Address”上方的行中添加一组括号:
)|((\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5])\.){3}(?#
不知道为什么。
我还将顶级域名的最小长度从3个字母减少到2个字母,以支持.co。英国和类似国家。
最后的代码:
/^(https?|ftp):\/\/(?# protocol
)(([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+(?# username
)(:([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+)?(?# password
)@)?(?# auth requires @
)((([a-z0-9]\.|[a-z0-9][a-z0-9-]*[a-z0-9]\.)*(?# domain segments AND
)[a-z][a-z0-9-]*[a-z0-9](?# top level domain OR
)|((\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5])\.){3}(?#
)(\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5])(?# IP address
))(:\d+)?(?# port
))(((\/+([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)*(?# path
)(\?([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)(?# query string
)?)?)?(?# path and query string optional
)(#([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)?(?# fragment
)$/i
这个修改后的版本没有根据URI规范进行检查,所以我不能保证它的合规性,它被修改为处理本地网络环境中的URL和两位tld以及其他类型的Web URL,并在我使用的PHP设置中更好地工作。
作为PHP代码:
define('URL_FORMAT',
'/^(https?):\/\/'. // protocol
'(([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+'. // username
'(:([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+)?'. // password
'@)?(?#'. // auth requires @
')((([a-z0-9]\.|[a-z0-9][a-z0-9-]*[a-z0-9]\.)*'. // domain segments AND
'[a-z][a-z0-9-]*[a-z0-9]'. // top level domain OR
'|((\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5])\.){3}'.
'(\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5])'. // IP address
')(:\d+)?'. // port
')(((\/+([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)*'. // path
'(\?([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)'. // query string
'?)?)?'. // path and query string optional
'(#([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)?'. // fragment
'$/i');
下面是一个PHP测试程序,它使用正则表达式验证各种url:
<?php
define('URL_FORMAT',
'/^(https?):\/\/'. // protocol
'(([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+'. // username
'(:([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+)?'. // password
'@)?(?#'. // auth requires @
')((([a-z0-9]\.|[a-z0-9][a-z0-9-]*[a-z0-9]\.)*'. // domain segments AND
'[a-z][a-z0-9-]*[a-z0-9]'. // top level domain OR
'|((\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5])\.){3}'.
'(\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5])'. // IP address
')(:\d+)?'. // port
')(((\/+([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)*'. // path
'(\?([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)'. // query string
'?)?)?'. // path and query string optional
'(#([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)?'. // fragment
'$/i');
/**
* Verify the syntax of the given URL.
*
* @access public
* @param $url The URL to verify.
* @return boolean
*/
function is_valid_url($url) {
if (str_starts_with(strtolower($url), 'http://localhost')) {
return true;
}
return preg_match(URL_FORMAT, $url);
}
/**
* String starts with something
*
* This function will return true only if input string starts with
* niddle
*
* @param string $string Input string
* @param string $niddle Needle string
* @return boolean
*/
function str_starts_with($string, $niddle) {
return substr($string, 0, strlen($niddle)) == $niddle;
}
/**
* Test a URL for validity and count results.
* @param url url
* @param expected expected result (true or false)
*/
$numtests = 0;
$passed = 0;
function test_url($url, $expected) {
global $numtests, $passed;
$numtests++;
$valid = is_valid_url($url);
echo "URL Valid?: " . ($valid?"yes":"no") . " for URL: $url. Expected: ".($expected?"yes":"no").". ";
if($valid == $expected) {
echo "PASS\n"; $passed++;
} else {
echo "FAIL\n";
}
}
echo "URL Tests:\n\n";
test_url("http://localserver/projects/public/assets/javascript/widgets/UserBoxMenu/widget.css", true);
test_url("http://www.google.com", true);
test_url("http://www.google.co.uk/projects/my%20folder/test.php", true);
test_url("https://myserver.localdomain", true);
test_url("http://192.168.1.120/projects/index.php", true);
test_url("http://192.168.1.1/projects/index.php", true);
test_url("http://projectpier-server.localdomain/projects/public/assets/javascript/widgets/UserBoxMenu/widget.css", true);
test_url("https://2.4.168.19/project-pier?c=test&a=b", true);
test_url("https://localhost/a/b/c/test.php?c=controller&arg1=20&arg2=20", true);
test_url("http://user:password@localhost/a/b/c/test.php?c=controller&arg1=20&arg2=20", true);
echo "\n$passed out of $numtests tests passed.\n\n";
?>
再次感谢regex的虚实!
其他回答
我用这个:/ ((https ?: \ / \ / | ftp: \ / \ / | www \) \ S + \[^。\ n ]+((?:\([^)]*\))|[^.,;:?!"'\ n \)\]<* ])+)/
它很短,但它处理了一些边缘情况,比如某些以括号结尾的维基百科链接(https://en.wikipedia.org/wiki/Sally_(name),这里投票最多的答案似乎没有涵盖这一点。
下面是RegexBuddy使用的。
(\b(https?|ftp|file)://)?[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]
它匹配以下这些(在** **标记内):
**http://www.regexbuddy.com**
**http://www.regexbuddy.com/**
**http://www.regexbuddy.com/index.html**
**http://www.regexbuddy.com/index.html?source=library**
**http://www.regexbuddy.com/index.html?source=library#copyright**
您可以从http://www.regexbuddy.com/download.html下载RegexBuddy。
这个怎么样:
^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9]\.[^\s]{2,})$
这些是测试用例:
你可以在这里试试:https://regex101.com/r/mS9gD7/41
^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$
现场演示:https://regex101.com/r/HUNasA/2
我已经测试了各种表达式来满足我的要求。
作为用户,我可以用以下字符串点击浏览器搜索栏:
有效的网址
https://www.google.com http://www.google.com http://google.com/ https://google.com/ www.google.com google.com https://www.google.com.ua http://www.google.com.ua http://google.com.ua https://google.com.ua/ www.google.com.ua google.com.ua https://mail.google.com http://mail.google.com mail.google.com
无效的url
http://google https://google.c 谷歌 谷歌。 .google .google.com goole.c ...
下面是我从URL中提取不同部分的正则表达式:
^ ((? (?): http | | ws ftp) s ? | sftp ):\/\/?)?([^:/\ s .#?]+\.[^:/\ s / # ?] + | localhost) (d: \ +)?((?:\/\ w +)*\/)?([\ w \-.]+[^#?\ s ]+)?([^#]+)?(#[\ w - *) ?美元
((?: ?: http | ftp | ws) s ? | sftp): \ \ / ?) ?(组1):提取协议 ([^: / \ s .#?]+\.[^:/\ # ?] + | localhost)(组2):提取的主机名 (: \ d +) ?(组3):提取端口号 ((?): \ / \ w +)*\/)?([\ w \-.]+[^#?\ s] +) ?(组4和组5):提取路径部分 ([^ #] +) ?(组6):提取查询部分 (# (\ w -) *) ?(组7):提取哈希部分
对于上面列出的正则表达式的每个部分,您可以删除结尾?强制(或加1使其兼性)。你也可以删除正则表达式开头的^和结尾的$,这样它就不需要匹配整个字符串了。
请参阅regex101。
注意:这个正则表达式不是100%安全的,可能接受一些字符串,这些字符串不一定是有效的url,但它确实验证了一些标准。它的主要目标是提取URL的不同部分,而不是验证它。