用于 URL 的 PHP 验证/正则表达式

我一直在寻找一个简单的正则表达式的网址,有人有一个方便,工作得很好?我没有找到一个具有 zend 框架验证类的实现,并且已经看到了几个实现。

187678 次浏览

我在一些项目中使用了这个,我不认为我遇到了什么问题,但是我肯定它不是详尽的:

$text = preg_replace(
'#((https?|ftp)://(\S*?\.\S*?))([\s)\[\]{},;"\':<]|\.\s|$)#i',
"'<a href=\"$1\" target=\"_blank\">$3</a>$4'",
$text
);

大部分的随机垃圾在结尾处理的情况下,像 http://domain.example.在一个句子(以避免匹配的尾随句)。我相信它可以被清理干净,但既然它工作。我或多或少只是从一个项目复制到另一个项目。

我已经很成功地使用了这个——我不记得我是从哪里得到它的了

$pattern = "/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i";

使用 filter_var()函数验证字符串是否为 URL:

var_dump(filter_var('example.com', FILTER_VALIDATE_URL));

在不必要时使用正则表达式是不好的做法。

EDIT : 小心,这个解决方案不是 unicode 安全的,也不是 XSS 安全的。如果您需要一个复杂的验证,也许最好到其他地方寻找。

根据 PHP 手册-parse _ URL 应该使用 没有来验证 URL。

不幸的是,filter_var('example.com', FILTER_VALIDATE_URL)似乎并没有表现得更好。

parse_url()filter_var()都将传递畸形的 URL,例如 http://...

因此在这种情况下-正则表达式 是更好的方法。

编辑:
正如 发生率所指出的,随着 PHP5.3.0(2009-06-30)的发布,这段代码已经被反对,因此应该相应地使用。


只是我个人的意见,但我已经开发了这个功能,并已经使用了一段时间,并取得了成功。它有很好的文档和分离,所以你可以很容易地改变它。

// Checks if string is a URL
// @param string $url
// @return bool
function isURL($url = NULL) {
if($url==NULL) return false;


$protocol = '(http://|https://)';
$allowed = '([a-z0-9]([-a-z0-9]*[a-z0-9]+)?)';


$regex = "^". $protocol . // must include the protocol
'(' . $allowed . '{1,63}\.)+'. // 1 or several sub domains with a max of 63 chars
'[a-z]' . '{2,6}'; // followed by a TLD
if(eregi($regex, $url)==true) return true;
else return false;
}

我觉得 Peter 的正则表达式有很多不对劲的地方。它允许在域名中使用各种特殊字符,并且不需要进行太多测试。

Frankie 的函数看起来不错,如果你不想要函数,可以用组件构建一个好的正则表达式,比如:

^(http://|https://)(([a-z0-9]([-a-z0-9]*[a-z0-9]+)?){1,63}\.)+[a-z]{2,6}

未经测试,但我觉得应该可以。

而且,欧文的回答看起来也不是百分百正确。我获取了正则表达式的域部分,并在正则表达式测试工具 http://erik.eae.net/playground/regexp/regexp.html上对其进行了测试

我写了这么一句话:

(\S*?\.\S*?)

在“ regexp”部分中 以及以下一行:

- 你好

在“示例文本”部分。

结果允许使用减号字符,因为 S 表示任何非空格字符。

请注意,Frankie 的 regex 处理负号,因为它的第一个字符包含以下部分:

[a-z0-9]

它不允许减号或其他特殊字符。

如果你想知道 url 是否真的存在:

function url_exist($url){//se passar a URL existe
$c=curl_init();
curl_setopt($c,CURLOPT_URL,$url);
curl_setopt($c,CURLOPT_HEADER,1);//get the header
curl_setopt($c,CURLOPT_NOBODY,1);//and *only* get the header
curl_setopt($c,CURLOPT_RETURNTRANSFER,1);//get the response as a string from curl_exec(), rather than echoing it
curl_setopt($c,CURLOPT_FRESH_CONNECT,1);//don't use a cached version of the url
if(!curl_exec($c)){
//echo $url.' inexists';
return false;
}else{
//echo $url.' exists';
return true;
}
//$httpcode=curl_getinfo($c,CURLINFO_HTTP_CODE);
//return ($httpcode<400);
}

根据 John Gruber(大胆火球) :

正方糖:

(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))

在 preg _ match ()中使用:

preg_match("/(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))/", $url)

下面是扩展的 regex 模式(带注释) :

(?xi)
\b
(                       # Capture 1: entire matched URL
(?:
https?://               # http or https protocol
|                       #   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
)
)

详情请浏览: Http://daringfireball.net/2010/07/improved_regex_for_matching_urls

function is_valid_url ($url="") {


if ($url=="") {
$url=$this->url;
}


$url = @parse_url($url);


if ( ! $url) {




return false;
}


$url = array_map('trim', $url);
$url['port'] = (!isset($url['port'])) ? 80 : (int)$url['port'];
$path = (isset($url['path'])) ? $url['path'] : '';


if ($path == '') {
$path = '/';
}


$path .= ( isset ( $url['query'] ) ) ? "?$url[query]" : '';






if ( isset ( $url['host'] ) AND $url['host'] != gethostbyname ( $url['host'] ) ) {
if ( PHP_VERSION >= 5 ) {
$headers = get_headers("$url[scheme]://$url[host]:$url[port]$path");
}
else {
$fp = fsockopen($url['host'], $url['port'], $errno, $errstr, 30);


if ( ! $fp ) {
return false;
}
fputs($fp, "HEAD $path HTTP/1.1\r\nHost: $url[host]\r\n\r\n");
$headers = fread ( $fp, 128 );
fclose ( $fp );
}
$headers = ( is_array ( $headers ) ) ? implode ( "\n", $headers ) : $headers;
return ( bool ) preg_match ( '#^HTTP/.*\s+[(200|301|302)]+\s#i', $headers );
}


return false;
}

我不认为在这种情况下使用正则表达式是一个明智的做法。要匹配所有的可能性是不可能的,即使匹配了,还是有可能 url 根本不存在。

这里有一个非常简单的方法来测试 url 是否真的存在并且是可读的:

if (preg_match("#^https?://.+#", $link) and @fopen($link,"r")) echo "OK";

(如果没有 preg_match,那么这也将验证服务器上的所有文件名)

我发现这对匹配 URL 最有用。

^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$
    function validateURL($URL) {
$pattern_1 = "/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i";
$pattern_2 = "/^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i";
if(preg_match($pattern_1, $URL) || preg_match($pattern_2, $URL)){
return true;
} else{
return false;
}
}

这就是你的答案 =)试着打破它,你不能! ! !

function link_validate_url($text) {
$LINK_DOMAINS = 'aero|arpa|asia|biz|com|cat|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|mobi|local';
$LINK_ICHARS_DOMAIN = (string) html_entity_decode(implode("", array( // @TODO completing letters ...
"&#x00E6;", // æ
"&#x00C6;", // Æ
"&#x00C0;", // À
"&#x00E0;", // à
"&#x00C1;", // Á
"&#x00E1;", // á
"&#x00C2;", // Â
"&#x00E2;", // â
"&#x00E5;", // å
"&#x00C5;", // Å
"&#x00E4;", // ä
"&#x00C4;", // Ä
"&#x00C7;", // Ç
"&#x00E7;", // ç
"&#x00D0;", // Ð
"&#x00F0;", // ð
"&#x00C8;", // È
"&#x00E8;", // è
"&#x00C9;", // É
"&#x00E9;", // é
"&#x00CA;", // Ê
"&#x00EA;", // ê
"&#x00CB;", // Ë
"&#x00EB;", // ë
"&#x00CE;", // Î
"&#x00EE;", // î
"&#x00CF;", // Ï
"&#x00EF;", // ï
"&#x00F8;", // ø
"&#x00D8;", // Ø
"&#x00F6;", // ö
"&#x00D6;", // Ö
"&#x00D4;", // Ô
"&#x00F4;", // ô
"&#x00D5;", // Õ
"&#x00F5;", // õ
"&#x0152;", // Œ
"&#x0153;", // œ
"&#x00FC;", // ü
"&#x00DC;", // Ü
"&#x00D9;", // Ù
"&#x00F9;", // ù
"&#x00DB;", // Û
"&#x00FB;", // û
"&#x0178;", // Ÿ
"&#x00FF;", // ÿ
"&#x00D1;", // Ñ
"&#x00F1;", // ñ
"&#x00FE;", // þ
"&#x00DE;", // Þ
"&#x00FD;", // ý
"&#x00DD;", // Ý
"&#x00BF;", // ¿
)), ENT_QUOTES, 'UTF-8');


$LINK_ICHARS = $LINK_ICHARS_DOMAIN . (string) html_entity_decode(implode("", array(
"&#x00DF;", // ß
)), ENT_QUOTES, 'UTF-8');
$allowed_protocols = array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'mailto', 'irc', 'ssh', 'sftp', 'webcal');


// Starting a parenthesis group with (?: means that it is grouped, but is not captured
$protocol = '((?:'. implode("|", $allowed_protocols) .'):\/\/)';
$authentication = "(?:(?:(?:[\w\.\-\+!$&'\(\)*\+,;=" . $LINK_ICHARS . "]|%[0-9a-f]{2})+(?::(?:[\w". $LINK_ICHARS ."\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})*)?)?@)";
$domain = '(?:(?:[a-z0-9' . $LINK_ICHARS_DOMAIN . ']([a-z0-9'. $LINK_ICHARS_DOMAIN . '\-_\[\]])*)(\.(([a-z0-9' . $LINK_ICHARS_DOMAIN . '\-_\[\]])+\.)*('. $LINK_DOMAINS .'|[a-z]{2}))?)';
$ipv4 = '(?:[0-9]{1,3}(\.[0-9]{1,3}){3})';
$ipv6 = '(?:[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7})';
$port = '(?::([0-9]{1,5}))';


// Pattern specific to external links.
$external_pattern = '/^'. $protocol .'?'. $authentication .'?('. $domain .'|'. $ipv4 .'|'. $ipv6 .' |localhost)'. $port .'?';


// Pattern specific to internal links.
$internal_pattern = "/^(?:[a-z0-9". $LINK_ICHARS ."_\-+\[\]]+)";
$internal_pattern_file = "/^(?:[a-z0-9". $LINK_ICHARS ."_\-+\[\]\.]+)$/i";


$directories = "(?:\/[a-z0-9". $LINK_ICHARS ."_\-\.~+%=&,$'#!():;*@\[\]]*)*";
// Yes, four backslashes == a single backslash.
$query = "(?:\/?\?([?a-z0-9". $LINK_ICHARS ."+_|\-\.~\/\\\\%=&,$'():;*@\[\]{} ]*))";
$anchor = "(?:#[a-z0-9". $LINK_ICHARS ."_\-\.~+%=&,$'():;*@\[\]\/\?]*)";


// The rest of the path for a standard URL.
$end = $directories .'?'. $query .'?'. $anchor .'?'.'$/i';


$message_id = '[^@].*@'. $domain;
$newsgroup_name = '(?:[0-9a-z+-]*\.)*[0-9a-z+-]*';
$news_pattern = '/^news:('. $newsgroup_name .'|'. $message_id .')$/i';


$user = '[a-zA-Z0-9'. $LINK_ICHARS .'_\-\.\+\^!#\$%&*+\/\=\?\`\|\{\}~\'\[\]]+';
$email_pattern = '/^mailto:'. $user .'@'.'(?:'. $domain .'|'. $ipv4 .'|'. $ipv6 .'|localhost)'. $query .'?$/';


if (strpos($text, '<front>') === 0) {
return false;
}
if (in_array('mailto', $allowed_protocols) && preg_match($email_pattern, $text)) {
return false;
}
if (in_array('news', $allowed_protocols) && preg_match($news_pattern, $text)) {
return false;
}
if (preg_match($internal_pattern . $end, $text)) {
return false;
}
if (preg_match($external_pattern . $end, $text)) {
return false;
}
if (preg_match($internal_pattern_file, $text)) {
return false;
}


return true;
}

这比简单的正则表达式要复杂一些,但是它允许不同类型的 url。

例子:

所有这些都应标记为有效。

function is_valid_url($url) {
// First check: is the url just a domain name? (allow a slash at the end)
$_domain_regex = "|^[A-Za-z0-9-]+(\.[A-Za-z0-9-]+)*(\.[A-Za-z]{2,})/?$|";
if (preg_match($_domain_regex, $url)) {
return true;
}


// Second: Check if it's a url with a scheme and all
$_regex = '#^([a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))$#';
if (preg_match($_regex, $url, $matches)) {
// pull out the domain name, and make sure that the domain is valid.
$_parts = parse_url($url);
if (!in_array($_parts['scheme'], array( 'http', 'https' )))
return false;


// Check the domain using the regex, stops domains like "-example.com" passing through
if (!preg_match($_domain_regex, $_parts['host']))
return false;


// This domain looks pretty valid. Only way to check it now is to download it!
return true;
}


return false;
}

请注意,对于希望允许的协议,有一个 in _ array 检查(目前该列表中只有 http 和 https)。

var_dump(is_valid_url('google.com'));         // true
var_dump(is_valid_url('google.com/'));        // true
var_dump(is_valid_url('http://google.com'));  // true
var_dump(is_valid_url('http://google.com/')); // true
var_dump(is_valid_url('https://google.com')); // true

我是这么做的。但是我想说的是,我对正则表达式不是很确定。但它应该起作用:)

$pattern = "#((http|https)://(\S*?\.\S*?))(\s|\;|\)|\]|\[|\{|\}|,|”|\"|'|:|\<|$|\.\s)#i";
$text = preg_replace_callback($pattern,function($m){
return "<a href=\"$m[1]\" target=\"_blank\">$m[1]</a>$m[4]";
},
$text);

这样你就不需要在你的模式上使用评估标记了。

希望对你有所帮助:)

有一个 PHP 本机函数:

$url = 'http://www.yoururl.co.uk/sub1/sub2/?param=1&param2/';


if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
// Wrong
}
else {
// Valid
}

返回筛选后的数据,如果筛选失败,返回 FALSE。

看这里

启发 在这个.NET StackOverflow 问题中在这篇文章中引用了这个问题有这个 URI 验证器(URI 意味着它验证 URL 和 URN)。

if( ! preg_match( "/^([a-z][a-z0-9+.-]*):(?:\\/\\/((?:(?=((?:[a-z0-9-._~!$&'()*+,;=:]|%[0-9A-F]{2})*))(\\3)@)?(?=(\\[[0-9A-F:.]{2,}\\]|(?:[a-z0-9-._~!$&'()*+,;=]|%[0-9A-F]{2})*))\\5(?::(?=(\\d*))\\6)?)(\\/(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/]|%[0-9A-F]{2})*))\\8)?|(\\/?(?!\\/)(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/]|%[0-9A-F]{2})*))\\10)?)(?:\\?(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/?]|%[0-9A-F]{2})*))\\11)?(?:#(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/?]|%[0-9A-F]{2})*))\\12)?$/i", $uri ) )
{
throw new \RuntimeException( "URI has not a valid format." );
}

我已经成功地在一个名为 Uri的 ValueObject 中对这个函数进行了单元测试,并通过 UriTest进行了测试。

Php (包含 URL 和 URN 的有效和无效用例)

<?php


declare( strict_types = 1 );


namespace XaviMontero\ThrasherPortage\Tests\Tour;


use XaviMontero\ThrasherPortage\Tour\Uri;


class UriTest extends \PHPUnit_Framework_TestCase
{
private $sut;


public function testCreationIsOfProperClassWhenUriIsValid()
{
$sut = new Uri( 'http://example.com' );
$this->assertInstanceOf( 'XaviMontero\\ThrasherPortage\\Tour\\Uri', $sut );
}


/**
* @dataProvider urlIsValidProvider
* @dataProvider urnIsValidProvider
*/
public function testGetUriAsStringWhenUriIsValid( string $uri )
{
$sut = new Uri( $uri );
$actual = $sut->getUriAsString();


$this->assertInternalType( 'string', $actual );
$this->assertEquals( $uri, $actual );
}


public function urlIsValidProvider()
{
return
[
[ 'http://example-server' ],
[ 'http://example.com' ],
[ 'http://example.com/' ],
[ 'http://subdomain.example.com/path/?parameter1=value1&parameter2=value2' ],
[ 'random-protocol://example.com' ],
[ 'http://example.com:80' ],
[ 'http://example.com?no-path-separator' ],
[ 'http://example.com/pa%20th/' ],
[ 'ftp://example.org/resource.txt' ],
[ 'file://../../../relative/path/needs/protocol/resource.txt' ],
[ 'http://example.com/#one-fragment' ],
[ 'http://example.edu:8080#one-fragment' ],
];
}


public function urnIsValidProvider()
{
return
[
[ 'urn:isbn:0-486-27557-4' ],
[ 'urn:example:mammal:monotreme:echidna' ],
[ 'urn:mpeg:mpeg7:schema:2001' ],
[ 'urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66' ],
[ 'rare-urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66' ],
[ 'urn:FOO:a123,456' ]
];
}


/**
* @dataProvider urlIsNotValidProvider
* @dataProvider urnIsNotValidProvider
*/
public function testCreationThrowsExceptionWhenUriIsNotValid( string $uri )
{
$this->expectException( 'RuntimeException' );
$this->sut = new Uri( $uri );
}


public function urlIsNotValidProvider()
{
return
[
[ 'only-text' ],
[ 'http//missing.colon.example.com/path/?parameter1=value1&parameter2=value2' ],
[ 'missing.protocol.example.com/path/' ],
[ 'http://example.com\\bad-separator' ],
[ 'http://example.com|bad-separator' ],
[ 'ht tp://example.com' ],
[ 'http://exampl e.com' ],
[ 'http://example.com/pa th/' ],
[ '../../../relative/path/needs/protocol/resource.txt' ],
[ 'http://example.com/#two-fragments#not-allowed' ],
[ 'http://example.edu:portMustBeANumber#one-fragment' ],
];
}


public function urnIsNotValidProvider()
{
return
[
[ 'urn:mpeg:mpeg7:sch ema:2001' ],
[ 'urn|mpeg:mpeg7:schema:2001' ],
[ 'urn?mpeg:mpeg7:schema:2001' ],
[ 'urn%mpeg:mpeg7:schema:2001' ],
[ 'urn#mpeg:mpeg7:schema:2001' ],
];
}
}

Php (值对象)

<?php


declare( strict_types = 1 );


namespace XaviMontero\ThrasherPortage\Tour;


class Uri
{
/** @var string */
private $uri;


public function __construct( string $uri )
{
$this->assertUriIsCorrect( $uri );
$this->uri = $uri;
}


public function getUriAsString()
{
return $this->uri;
}


private function assertUriIsCorrect( string $uri )
{
// https://stackoverflow.com/questions/30847/regex-to-validate-uris
// http://snipplr.com/view/6889/regular-expressions-for-uri-validationparsing/


if( ! preg_match( "/^([a-z][a-z0-9+.-]*):(?:\\/\\/((?:(?=((?:[a-z0-9-._~!$&'()*+,;=:]|%[0-9A-F]{2})*))(\\3)@)?(?=(\\[[0-9A-F:.]{2,}\\]|(?:[a-z0-9-._~!$&'()*+,;=]|%[0-9A-F]{2})*))\\5(?::(?=(\\d*))\\6)?)(\\/(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/]|%[0-9A-F]{2})*))\\8)?|(\\/?(?!\\/)(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/]|%[0-9A-F]{2})*))\\10)?)(?:\\?(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/?]|%[0-9A-F]{2})*))\\11)?(?:#(?=((?:[a-z0-9-._~!$&'()*+,;=:@\\/?]|%[0-9A-F]{2})*))\\12)?$/i", $uri ) )
{
throw new \RuntimeException( "URI has not a valid format." );
}
}
}

运行单元测试

在46个测试中有65个断言。注意:中有两个数据提供程序用于有效表达式,另外两个数据提供程序用于无效表达式。一个用于 URL,另一个用于 URN。如果您使用的是5.6 * 或更早版本的 PhpUnit,那么您需要将两个数据提供程序合并为一个提供程序。

xavi@bromo:~/custom_www/hello-trip/mutant-migrant$ vendor/bin/phpunit
PHPUnit 5.7.3 by Sebastian Bergmann and contributors.


..............................................                    46 / 46 (100%)


Time: 82 ms, Memory: 4.00MB


OK (46 tests, 65 assertions)

代码覆盖

在这个示例 URI 检查器中有100% 的代码覆盖率。

下面是一个使用 RegEx 的 URL 验证简单类,然后将该域与流行的 RBL (实时黑洞列表)服务器进行交叉引用:

安装:

require 'URLValidation.php';

用法:

require 'URLValidation.php';
$urlVal = new UrlValidation(); //Create Object Instance

添加一个 URL 作为 domain()方法的参数并检查返回值。

$urlArray = ['http://www.bokranzr.com/test.php?test=foo&test=dfdf', 'https://en-gb.facebook.com', 'https://www.google.com'];
foreach ($urlArray as $k=>$v) {


echo var_dump($urlVal->domain($v)) . ' URL: ' . $v . '<br>';


}

输出:

bool(false) URL: http://www.bokranzr.com/test.php?test=foo&test=dfdf
bool(true) URL: https://en-gb.facebook.com
bool(true) URL: https://www.google.com

正如你在上面看到的, www.bokranzr.com 通过 RBL 被列为恶意网站,所以域名被返回为 false。

"/(http(s?):\/\/)([a-z0-9\-]+\.)+[a-z]{2,4}(\.[a-z]{2,4})*(\/[^ ]+)*/i"
  1. (http (s?) ://)意思是 http://或 https://

  2. ([ a-z0-9-] + .) + = > 2.0[ a-z0-9-]表示任何 a-z 字符或任何0-9或(-)符号

                 2.1 (+) means the character can be one or more ex: a1w,
    a9-,c559s, f)
    
    
    2.2 \. is (.)sign
    
    
    2.3. the (+) sign after ([a-z0-9\-]+\.) mean do 2.1,2.2,2.3
    at least 1 time
    ex: abc.defgh0.ig, aa.b.ced.f.gh. also in case www.yyy.com
    
    
    3.[a-z]{2,4} mean a-z at least 2 character but not more than
    4 characters for check that there will not be
    the case
    ex: https://www.google.co.kr.asdsdagfsdfsf
    
    
    4.(\.[a-z]{2,4})*(\/[^ ]+)* mean
    
    
    4.1 \.[a-z]{2,4} means like number 3 but start with
    (.)sign
    
    
    4.2 * means (\.[a-z]{2,4})can be use or not use never mind
    
    
    4.3 \/ means \
    4.4 [^ ] means any character except blank
    4.5 (+) means do 4.3,4.4,4.5 at least 1 times
    4.6 (*) after (\/[^ ]+) mean use 4.3 - 4.5 or not use
    no problem
    
    
    use for case https://stackoverflow.com/posts/51441301/edit
    
    
    5. when you use regex write in "/ /" so it come
    

    “/(http (s?) ://)([ a-z0-9-] + .) + [ a-z ]{2,4}(. [ a-z ]{2,4}) (/[^ ]+)/i”

                   6. almost forgot: letter i on the back mean ignore case of
    Big letter or small letter ex: A same as a, SoRRy same
    as sorry.
    

Note : Sorry for bad English. My country not use it well.

对于任何使用 WordPress 开发的人来说,只要使用

esc_url_raw($url) === $url

验证一个 URL (这是 WordPress 在 esc_url_raw上的文档)。它处理 URL 比 filter_var($url, FILTER_VALIDATE_URL)好得多,因为它是 unicode 和 XSS-safe。(这里有一篇很好的文章提到了 filter_var的所有问题)。

我使用过的最好的 URL 正则表达式:

function valid_URL($url){
return preg_match('%^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@|\d{1,3}(?:\.\d{1,3}){3}|(?:(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)(?:\.(?:[a-z\d\x{00a1}-\x{ffff}]+-?)*[a-z\d\x{00a1}-\x{ffff}]+)*(?:\.[a-z\x{00a1}-\x{ffff}]{2,6}))(?::\d+)?(?:[^\s]*)?$%iu', $url);
}

例子:

valid_URL('https://twitter.com'); // true
valid_URL('http://twitter.com');  // true
valid_URL('http://twitter.co');   // true
valid_URL('http://t.co');         // true
valid_URL('http://twitter.c');    // false
valid_URL('htt://twitter.com');   // false


valid_URL('http://example.com/?a=1&b=2&c=3'); // true
valid_URL('http://127.0.0.1');    // true
valid_URL('');                    // false
valid_URL(1);                     // false

资料来源: http://urlregex.com/