w3school regular preg_match_all preg_match pattern examples ejemplos php regex url validation

regular - Validación/regex de PHP para URL



preg_match php w3school (18)

Aquí hay una clase simple para la Validación de URL que usa RegEx y luego hace una referencia cruzada del dominio contra los populares servidores RBL (Realtime Blackhole Lists):

Instalar:

require ''URLValidation.php'';

Uso:

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

Agregue una URL como el parámetro del método de domain() y verifique la devolución.

$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>''; }

Salida:

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

Como puede ver arriba, www.bokranzr.com figura como sitio web malicioso a través de un RBL, por lo que el dominio se devolvió como falso.

He estado buscando una expresión regular simple para las URL, ¿alguien tiene una a mano que funcione bien? No encontré uno con las clases de validación de zend framework y he visto varias implementaciones.

Gracias


En caso de que quiera saber si la URL realmente existe:

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); }


Esta es la forma en que lo hice. Pero quiero mencionar que no estoy tan seguro sobre la expresión regular. Pero debería funcionar tú :)

$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);

De esta forma, no necesitará el marcador eval en su patrón.

Espero eso ayude :)


Hay una función nativa de PHP para eso:

$url = ''http://www.yoururl.co.uk/sub1/sub2/?param=1&param2/''; if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) { // Wrong } else { // Valid }

Devuelve los datos filtrados, o FALSE si el filtro falla.

Verifíquelo aquí


He encontrado que este es el más útil para hacer coincidir una URL.

^(https?:////)?([/da-z/.-]+)/.([a-z/.]{2,6})([///w /.-]*)*//?$


Inspirado en esta pregunta de .NET y en este artículo al que se hace referencia de esa pregunta, existe este validador de URI (URI significa que valida tanto la URL como la 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." ); }

He probado con éxito esta función dentro de un ValueObject que realicé con el nombre Uri y que fue probado por UriTest .

UriTest.php (contiene casos válidos y no válidos para URL y 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'' ], ]; } }

Uri.php (Objeto de valor)

<?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://.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." ); } } }

Ejecución de pruebas de la unidad

Hay 65 afirmaciones en 46 pruebas. Precaución: hay 2 proveedores de datos para expresiones válidas y 2 más para expresiones no válidas. Una es para URL y la otra para URN. Si está utilizando una versión de PhpUnit de v5.6 * o anterior, debe unir los dos proveedores de datos en uno solo.

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)

Cobertura de código

Hay un 100% de cobertura de código en este comprobador de URI de muestra.


Lo usé en algunos proyectos, no creo haber tenido problemas, pero estoy seguro de que no es exhaustivo:

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

La mayoría de la basura al azar al final es para tratar situaciones como http://domain.com. en una oración (para evitar coincidir con el período posterior). Estoy seguro de que podría limpiarse, pero dado que funcionó. Más o menos lo he copiado de proyecto en proyecto.


No creo que usar expresiones regulares sea algo inteligente en este caso. Es imposible hacer coincidir todas las posibilidades e, incluso si lo hiciste, aún existe la posibilidad de que la URL simplemente no exista.

Aquí hay una manera muy simple de probar si la URL realmente existe y es legible:

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

(Si no hay preg_match , esto también validaría todos los nombres de archivo en su servidor)


OK, entonces esto es un poco más complejo que una simple expresión regular, pero permite diferentes tipos de URL.

Ejemplos:

Todo lo cual debe ser marcado como válido.

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; }

Tenga en cuenta que hay una verificación in_array para los protocolos que desea permitir (actualmente solo http y https están en esa lista).

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


Peter''s Regex no me parece correcto por muchas razones. Permite todo tipo de caracteres especiales en el nombre de dominio y no prueba mucho.

La función de Frankie se ve bien para mí y puedes construir una buena expresión regular de los componentes si no quieres una función, así:

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

No probado, pero creo que debería funcionar.

Además, la respuesta de Owen tampoco se ve al 100%. Tomé el dominio parte de la expresión regular y lo probé en una herramienta de prueba Regex http://erik.eae.net/playground/regexp/regexp.html

Pongo la siguiente línea:

(/S*?/./S*?)

en la sección "regexp" y en la siguiente línea:

-hello.com

en la sección "texto de muestra".

El resultado permitió que pase el caracter negativo. Porque / S significa cualquier carácter no espacial.

Tenga en cuenta que la expresión regular de Frankie maneja el signo menos porque tiene esta parte para el primer carácter:

[a-z0-9]

Lo cual no permitirá el menos o cualquier otro carácter especial.


Según John Gruber (Daring Fireball):

Regex:

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

usando en 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)

Aquí está el patrón de expresiones regulares extendido (con comentarios):

(?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 ) )

Para obtener más información, consulte: http://daringfireball.net/2010/07/improved_regex_for_matching_urls


Según el manual de PHP, parse_url no debe usarse para validar una URL.

Desafortunadamente, parece que filter_var(''example.com'', FILTER_VALIDATE_URL) no funciona mejor.

Ambos parse_url() y filter_var() pasarán URL mal formadas como http://...

Por lo tanto, en este caso, la expresión regular es el mejor método.


Utilicé este con éxito: no recuerdo de dónde lo saqué

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


Utilice la función filter_var() para validar si una cadena es URL o no:

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

Es una mala práctica usar expresiones regulares cuando no es necesario.

EDITAR : tenga cuidado, esta solución no es segura para unicode y no es segura para XSS. Si necesita una validación compleja, quizás sea mejor buscar en otro lado.


Y ahí está tu respuesta =) ¡Trata de romperlo, no puedes!

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; }


Editar:
Como indica la incidence , este código ha sido DEPURADO con el lanzamiento de PHP 5.3.0 (2009-06-30) y debe usarse en consecuencia.

Solo mi granito de arena, pero he desarrollado esta función y la he estado utilizando por un tiempo con éxito. Está bien documentado y separado para que pueda cambiarlo fácilmente.

// 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; }


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 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; }