2008-08-26 54 views
106

Dada la URL (una sola línea):
http://test.example.com/dir/subdir/file.htmlpartes Obtención de una dirección URL (expresiones regulares)

¿Cómo puedo extraer las siguientes partes el uso de expresiones regulares:

  1. el subdominio (prueba)
  2. el dominio (example.com)
  3. el camino sin el archivo (/ dir/subdirectorio /)
  4. el archivo (archivo.html)
  5. El camino con el archivo (/dir/subdir/file.html)
  6. La URL sin la ruta (http://test.example.com)
  7. (añadir cualquier otro que crea que puede ser útil)

la expresión regular debería funcionar correctamente incluso si ingreso la siguiente URL:
http://example.example.com/example/example/example.html

Gracias.

+7

favor nos explican por qué esto tiene que ser hecho con una expresión regular. Si es tarea, dígalo porque esa es su restricción. De lo contrario, hay mejores soluciones específicas de idioma que usar una expresión regular. –

+1

Los enlaces a la primera y la última muestra están rotos. –

+0

Aquí puede encontrar cómo extraer esquema, dominio, TLD, puerto y ruta de consulta: https://stackoverflow.com/questions/9760588/how-do-you-extract-a-url-from-a-string-using -python/31952097 # 31952097 –

Respuesta

121

Una sola expresión regular para analizar y ruptura un URL completo incluyendo parámetros de consulta y anclajes, por ejemplo,

https://www.google.com/dir/1/2/search.html?arg=0-a&arg1=1-b&arg3-c#hash

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(.*)?(#[\w\-]+)?$

posiciones RexEx:

url: RegExp [ '$ &'],

protocolo: RegExp $ 2,

host:.. RegExp $ 3 ,

ruta:. RegExp $ 4,

archivo:. RegExp $ 6,

consulta: RegExp $ 7,

de hash:.. RegExp $ 8

usted podría entonces analizar aún más el anfitrión ('.' delimitado) con bastante facilidad.

Lo que gustaría hacer es usar algo como esto:

/* 
    ^(.*:)//([A-Za-z0-9\-\.]+)(:[0-9]+)?(.*)$ 
*/ 
proto $1 
host $2 
port $3 
the-rest $4 

el análisis sintáctico más 'el resto' de ser lo más específico posible. Hacerlo en una expresión regular es, bueno, un poco loco.

+3

El enlace http://codesnippets.joyent.com/posts/show/523 no funciona a partir del 20 de octubre '10 – W3Max

+19

El problema es esta parte: '(. *)?' Dado que el Kleene star ya acepta 0 o más, la parte '?' (0 o 1) lo confunde. Lo arreglé cambiando '(. *)?' A '(. +)?'. También podría eliminar el '?' – rossipedia

+1

Good catch Bryan. No voy a editar la respuesta, ya que la cité del enlace (ahora desaparecido), pero modifiqué tu comentario para que la aclaración sea más visible. – hometoast

6

Esta no es una respuesta directa, pero la mayoría de las bibliotecas web tienen una función que realiza esta tarea. La función a menudo se llama algo similar a CrackUrl. Si tal función existe, úselo, casi se garantiza que será más confiable y más eficiente que cualquier código hecho a mano.

5

El subdominio y el dominio son difíciles porque el subdominio puede tener varias partes, al igual que el dominio de nivel superior, http://sub1.sub2.domain.co.uk/

the path without the file : http://[^/]+/((?:[^/]+/)*(?:[^/]+$)?) 
the file : http://[^/]+/(?:[^/]+/)*((?:[^/.]+\.)+[^/.]+)$ 
the path with the file : http://[^/]+/(.*) 
the URL without the path : (http://[^/]+/) 

(Markdown no es muy amigable para expresiones regulares)

+1

Muy útil - Agregué un '(http? S?): // [^ /] + /)' adicional para también tomar https – Mojowen

0

El uso de expresiones regulares http://www.fileformat.info/tool/regex.htm de hometoast funciona muy bien.

Pero este es el trato, quiero usar diferentes patrones de expresiones regulares en diferentes situaciones en mi programa.

Por ejemplo, tengo esta URL y tengo una enumeración que enumera todas las URL admitidas en mi programa. Cada objeto en la enumeración tiene un método getRegexPattern que devuelve el patrón de expresiones regulares que luego se usará para comparar con una URL. Si el patrón de expresiones regulares particular devuelve verdadero, entonces sé que este URL es compatible con mi programa. Entonces, cada enumeración tiene su propia expresión regular dependiendo de dónde debe verse dentro de la URL.

La sugerencia de Hometoast es genial, pero en mi caso, creo que no ayudaría (a menos que copie y pegue la misma expresión regular en todas las enumeraciones).

Es por eso que quería la respuesta para dar la expresión regular para cada situación por separado. Aunque +1 para hometoast. ;)

0

Sé que estás diciendo que es independiente del idioma, pero ¿puedes decirnos qué estás utilizando solo para que sepamos qué capacidades de expresiones regulares tienes?

Si usted tiene las capacidades para los partidos no captura, se puede modificar la expresión de hometoast modo que subexpresiones que usted no está interesado en la captura se establecen así:

(?:SOMESTUFF)

usted todavía tiene que copiar y pegar (y modificar ligeramente) la Regex en múltiples lugares, pero tiene sentido; no solo está verificando si existe la subexpresión, sino si existe como parte de una URL. Usar el modificador que no captura para las subexpresiones puede darte lo que necesitas y nada más, lo que, si te leo correctamente, es lo que quieres.

Al igual que una pequeña nota pequeña, la expresión de hometoast no necesita poner corchetes alrededor de la 's' para 'https', ya que él solo tiene un carácter allí. Los cuantificadores cuantifican el carácter (o clase de carácter o subexpresión) que los precede directamente. Por lo tanto:

https?

coincidiría con 'http' o 'https' muy bien.

1

Java ofrece una clase de URL que hará esto. Query URL Objects.

En una nota lateral, PHP ofrece parse_url().

+0

Parece que esto no analiza el subdominio? –

+0

Asker pidió expresiones regulares. La clase URL abrirá una conexión cuando la crees. – MikeNereson

+0

"La clase URL abrirá una conexión cuando la cree" - eso es incorrecto, solo cuando llama a métodos como connect(). Pero es cierto que java.net.URL es algo pesado. Para este caso de uso, java.net.URI es mejor. –

30

Encontré la respuesta más votada (la respuesta de hometoast) no funciona perfectamente para mí. Dos problemas:

  1. No puede manejar el número de puerto.
  2. La parte hash está rota.

La siguiente es una versión modificada:

^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/\w+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$ 

posición de las partes son las siguientes:

int SCHEMA = 2, DOMAIN = 3, PORT = 5, PATH = 6, FILE = 8, QUERYSTRING = 9, HASH = 12 

Editar publicado por el usuario anon:

function getFileName(path) { 
    return path.match(/^((http[s]?|ftp):\/)?\/?([^:\/\s]+)(:([^\/]*))?((\/[\w\/-]+)*\/)([\w\-\.]+[^#?\s]+)(\?([^#]*))?(#(.*))?$/i)[8]; 
} 
+23

esto no funciona para mí. Odio la expresión regular ... – CyberJunkie

+0

Parece que funciona para mí: https://regex101.com/r/PL862w/1 –

+0

Tenga en cuenta que no funciona si la URL no tiene una ruta después del dominio, p. Ej. 'http: // www.example.com' o si la ruta es un solo caracter como' http: // www.example.com/a'. –

4
/^((?P<scheme>https?|ftp):\/)?\/?((?P<username>.*?)(:(?P<password>.*?)|)@)?(?P<hostname>[^:\/\s]+)(?P<port>:([^\/]*))?(?P<path>(\/\w+)*\/)(?P<filename>[-\w.]+[^#?\s]*)?(?P<query>\?([^#]*))?(?P<fragment>#(.*))?$/ 

F rom mi respuesta en un similar question. Funciona mejor que algunos de los otros mencionados porque tenían algunos errores (como no admitir nombre de usuario/contraseña, no admitir nombres de archivo de un solo carácter, fragmentos de identificadores que se rompen).

0

regexp para obtener la ruta URL sin el archivo.

url = 'http://domain/dir1/dir2/somefile' url.scan (/^(http: // [^ /] +) ((:?/[^ /] +) + (= /))/(???? : [^ /] +)? $/i) .to_s

Puede ser útil para agregar una ruta relativa a esta url.

2

Puede obtener todos los http/https, host, puerto, ruta, así como consultas mediante el uso de objetos URI en .NET. solo la tarea difícil es dividir el host en subdominio, nombre de dominio y TLD.

No hay un estándar para hacerlo y no se puede simplemente usar el análisis sintáctico de cadenas o RegEx para producir el resultado correcto. Al principio, estoy usando la función RegEx pero no todas las URL pueden analizar el subdominio correctamente. La forma de práctica es usar una lista de TLD. Después de definir un TLD para una URL, la parte izquierda es dominio y el resto es subdominio.

Sin embargo, la lista debe mantenerlo ya que son posibles nuevos TLD. El momento actual que sé es publicsuffix.org mantener la última lista y puede usar las herramientas domainname-parser del código de google para analizar la lista de sufijos públicos y obtener el subdominio, dominio y TLD fácilmente mediante el uso del objeto DomainName: domainName.SubDomain, domainName .Domain y domainName.TLD.

Esto responde también atento: Get the subdomain from a URL

CaLLMeLaNN

2

Yo recomendaría no usar expresiones regulares. Una llamada API como WinHttpCrackUrl() es menos propensa a errores.

http://msdn.microsoft.com/en-us/library/aa384092%28VS.85%29.aspx

+4

Y también muy específico de la plataforma. – Andir

+2

Creo que el objetivo era utilizar una biblioteca, en lugar de reinventar la rueda. Ruby, Python, Perl tienen herramientas para dividir las URL, así que cógelas en lugar de implementar un mal patrón. –

5

Esta versión mejorada debería funcionar tan fiable como un analizador.

// Applies to URI, not just URL or URN: 
    // http://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Relationship_to_URL_and_URN 
    // 
    // http://labs.apache.org/webarch/uri/rfc/rfc3986.html#regexp 
    // 
    // (?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))? 
    // 
    // http://en.wikipedia.org/wiki/URI_scheme#Generic_syntax 
    // 
    // [email protected] matches the entire uri 
    // $1 matches scheme (ftp, http, mailto, mshelp, ymsgr, etc) 
    // $2 matches authority (host, user:[email protected], etc) 
    // $3 matches path 
    // $4 matches query (http GET REST api, etc) 
    // $5 matches fragment (html anchor, etc) 
    // 
    // Match specific schemes, non-optional authority, disallow white-space so can delimit in text, and allow 'www.' w/o scheme 
    // Note the schemes must match ^[^\s|:/?#]+(?:\|[^\s|:/?#]+)*$ 
    // 
    // (?:()(www\.[^\s/?#]+\.[^\s/?#]+)|(schemes)://([^\s/?#]*))([^\s?#]*)(?:\?([^\s#]*))?(#(\S*))? 
    // 
    // Validate the authority with an orthogonal RegExp, so the RegExp above won’t fail to match any valid urls. 
    function uriRegExp(flags, schemes/* = null*/, noSubMatches/* = false*/) 
    { 
     if(!schemes) 
     schemes = '[^\\s:\/?#]+' 
     else if(!RegExp(/^[^\s|:\/?#]+(?:\|[^\s|:\/?#]+)*$/).test(schemes)) 
     throw TypeError('expected URI schemes') 
     return noSubMatches ? new RegExp('(?:www\\.[^\\s/?#]+\\.[^\\s/?#]+|' + schemes + '://[^\\s/?#]*)[^\\s?#]*(?:\\?[^\\s#]*)?(?:#\\S*)?', flags) : 
     new RegExp('(?:()(www\\.[^\\s/?#]+\\.[^\\s/?#]+)|(' + schemes + ')://([^\\s/?#]*))([^\\s?#]*)(?:\\?([^\\s#]*))?(?:#(\\S*))?', flags) 
    } 

    // http://en.wikipedia.org/wiki/URI_scheme#Official_IANA-registered_schemes 
    function uriSchemesRegExp() 
    { 
     return 'about|callto|ftp|gtalk|http|https|irc|ircs|javascript|mailto|mshelp|sftp|ssh|steam|tel|view-source|ymsgr' 
    } 
2

Lamentablemente, esto no funciona con algunas URL.Tomemos, por ejemplo, ésta: http://www.example.org/&value=329

Tampoco & valor = 329

O incluso sin parámetros en absoluto (una simple URL)!

Entiendo que la expresión regular está esperando una URL seriamente compleja/larga, pero también debería poder funcionar en las más simples, ¿no?

10

necesitaba una expresión regular para que coincida con todas las URL e hizo éste:

/(?:([^\:]*)\:\/\/)?(?:([^\:\@]*)(?:\:([^\@]*))?\@)?(?:([^\/\:]*)\.(?=[^\.\/\:]*\.[^\.\/\:]*))?([^\.\/\:]*)(?:\.([^\/\.\:]*))?(?:\:([0-9]*))?(\/[^\?#]*(?=.*?\/)\/)?([^\?#]*)?(?:\?([^#]*))?(?:#(.*))?/ 

Coincide con todas las URL, cualquier protocolo, incluso URLs como

ftp://user:[email protected]:8080/dir1/dir2/file.php?param1=value1#hashtag 

El resultado (en JavaScript) miradas de esta manera:

["ftp", "user", "pass", "www.cs", "server", "com", "8080", "/dir1/dir2/", "file.php", "param1=value1", "hashtag"] 

una URL como

mailto://[email protected] 

se parece a esto:

["mailto", "admin", undefined, "www.cs", "server", "com", undefined, undefined, undefined, undefined, undefined] 
+0

Si quiere hacer coincidir todo el dominio/dirección IP (no separados por puntos) use este: '/ (?: ([^ \:] *) \: \/\ /)? (?: ([^ \ : \ @] *) (?: \: ([^ \ @] *))? \ @)? (?: ([^ \/\:] *))? (?: \: ([0-9 ] *))? \/(\/[^ \? #] * (? =. *? \ /) \ /)? ([^ \? #] *)? (?: \? ([^ #] *))? (?: # (. *))?/' – lepe

75

Soy consciente de que estoy tarde a la fiesta, pero hay una forma sencilla de permitir que el navegador Procesar una URL para usted sin una expresión regular:

var a = document.createElement('a'); 
a.href = 'http://www.example.com:123/foo/bar.html?fox=trot#foo'; 

['href','protocol','host','hostname','port','pathname','search','hash'].forEach(function(k) { 
    console.log(k+':', a[k]); 
}); 

/*//Output: 
href: http://www.example.com:123/foo/bar.html?fox=trot#foo 
protocol: http: 
host: www.example.com:123 
hostname: www.example.com 
port: 123 
pathname: /foo/bar.html 
search: ?fox=trot 
hash: #foo 
*/ 
+5

Dado que la pregunta original fue etiquetada como" agnóstica del lenguaje ", ¿qué idioma es este? – MarkHu

+0

tenga en cuenta que esta solución requiere una existencia de prefijo de protocolo, por ejemplo 'http: //', para la correcta visualización de las propiedades de protocolo, host y nombre de host. De lo contrario, el comienzo de la URL hasta la primera barra pasa a la propiedad del protocolo. –

+0

Creo esto, aunque simple, pero mucho más lento que el análisis RegEx. – demisx

1

Aquí hay uno que está completo y no se basa en ningún protocolo.

function getServerURL(url) { 
     var m = url.match("(^(?:(?:.*?)?//)?[^/?#;]*)"); 
     console.log(m[1]) // Remove this 
     return m[1]; 
    } 

getServerURL("http://dev.test.se") 
getServerURL("http://dev.test.se/") 
getServerURL("//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js") 
getServerURL("//") 
getServerURL("www.dev.test.se/sdas/dsads") 
getServerURL("www.dev.test.se/") 
getServerURL("www.dev.test.se?abc=32") 
getServerURL("www.dev.test.se#abc") 
getServerURL("//dev.test.se?sads") 
getServerURL("http://www.dev.test.se#321") 
getServerURL("http://localhost:8080/sads") 
getServerURL("https://localhost:8080?sdsa") 

imprime

http://dev.test.se 

http://dev.test.se 

//ajax.googleapis.com 

// 

www.dev.test.se 

www.dev.test.se 

www.dev.test.se 

www.dev.test.se 

//dev.test.se 

http://www.dev.test.se 

http://localhost:8080 

https://localhost:8080 
2

Ninguna de las anteriores trabajó para mí. Esto es lo que terminé usando:

/^(?:((?:https?|s?ftp):)\/\/)([^:\/\s]+)(?::(\d*))?(?:\/([^\s?#]+)?([?][^?#]*)?(#.*)?)?/ 
4

proponer una solución mucho más fácil de leer (en Python, pero se aplica a cualquier expresión regular):

def url_path_to_dict(path): 
    pattern = (r'^' 
       r'((?P<schema>.+?)://)?' 
       r'((?P<user>.+?)(:(?P<password>.*?))[email protected])?' 
       r'(?P<host>.*?)' 
       r'(:(?P<port>\d+?))?' 
       r'(?P<path>/.*?)?' 
       r'(?P<query>[?].*?)?' 
       r'$' 
       ) 
    regex = re.compile(pattern) 
    m = regex.match(path) 
    d = m.groupdict() if m is not None else None 

    return d 

def main(): 
    print url_path_to_dict('http://example.example.com/example/example/example.html') 

Lienzo:

{ 
'host': 'example.example.com', 
'user': None, 
'path': '/example/example/example.html', 
'query': None, 
'password': None, 
'port': None, 
'schema': 'http' 
} 
6

que estaba tratando para resolver esto en javascript, que debe ser manejado por:

var url = new URL('http://a:[email protected]:890/path/[email protected]/foo.js?foo=bar&bingobang=&[email protected]#foobar/bing/[email protected]?bang'); 

ya que (en Chrome, al menos) se analiza sintácticamente a:

{ 
    "hash": "#foobar/bing/[email protected]?bang", 
    "search": "?foo=bar&bingobang=&[email protected]", 
    "pathname": "/path/[email protected]/foo.js", 
    "port": "890", 
    "hostname": "example.com", 
    "host": "example.com:890", 
    "password": "b", 
    "username": "a", 
    "protocol": "http:", 
    "origin": "http://example.com:890", 
    "href": "http://a:[email protected]:890/path/[email protected]/foo.js?foo=bar&bingobang=&[email protected]#foobar/bing/[email protected]?bang" 
} 

Sin embargo, este no es el navegador cruz (https://developer.mozilla.org/en-US/docs/Web/API/URL), así que adoquinadas esto juntos para tirar de las mismas partes a cabo como anteriormente:

^(?:(?:(([^:\/#\?]+:)?(?:(?:\/\/)(?:(?:(?:([^:@\/#\?]+)(?:\:([^:@\/#\?]*))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((?:\/?(?:[^\/\?#]+\/+)*)(?:[^\?#]*)))?(\?[^#]+)?)(#.*)? 

crédito para esta expresión regular va a https://gist.github.com/rpflorence que publicó este jsperf http://jsperf.com/url-parsing (originalmente encontrado aquí: https://gist.github.com/jlong/2428561#comment-310066) que subió con la expresión regular esto se basó originalmente en.

Las partes son en este orden:

var keys = [ 
    "href",     // http://user:[email protected]:81/directory/file.ext?query=1#anchor 
    "origin",     // http://user:[email protected]:81 
    "protocol",    // http: 
    "username",    // user 
    "password",    // pass 
    "host",     // host.com:81 
    "hostname",    // host.com 
    "port",     // 81 
    "pathname",    // /directory/file.ext 
    "search",     // ?query=1 
    "hash"      // #anchor 
]; 

También hay una pequeña biblioteca que lo envuelve y proporciona Parámetros de consulta:

https://github.com/sadams/lite-url (también disponibles en la glorieta)

Si tiene una mejora, crea una solicitud de extracción con más pruebas y la aceptaré y fusionaré con agradecimiento.

+0

Esto es genial, pero realmente podría funcionar con una versión como esta que saca subdominios en lugar del host duplicado, nombre de host. Entonces, si tuviera 'http: // test1.dev.mydomain.com /' por ejemplo, sacaría 'test1.dev'. – Lankymart

+0

Esto funciona muy bien. He estado buscando una manera de extraer los parámetros de autenticación inusual de las URL, y esto funciona muy bien. –

41

Llego unos años tarde a la fiesta, pero me sorprende que nadie haya mencionado que la especificación Uniform Resource Identifier tenga un section on parsing URIs with a regular expression. . La expresión regular, escrito por Berners-Lee, et al, es:

^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))? 
12   3 4   5  6 7  8 9 

Los números en la segunda línea de arriba son sólo para ayudar a la legibilidad; indican los puntos de referencia para cada subexpresión (es decir, cada paréntesis apareados). Nos referimos al valor coincidente para la subexpresión como $. Por ejemplo, igualando la expresión anterior a

http://www.ics.uci.edu/pub/ietf/uri/#Related

resultados en los siguientes partidos subexpresión:

$1 = http: 
$2 = http 
$3 = //www.ics.uci.edu 
$4 = www.ics.uci.edu 
$5 = /pub/ietf/uri/ 
$6 = <undefined> 
$7 = <undefined> 
$8 = #Related 
$9 = Related 

Por lo que vale la pena, me di cuenta que tenía que escapar de las barras diagonales en JavaScript :

^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?

+4

¡excelente respuesta! Elegir algo de un RFC nunca puede malograr lo que debe hacer – frankster

+0

Esto no analiza los parámetros de consulta –

+1

Este es el mejor caso. Específicamente, esto aborda dos problemas que he visto con los otros: '1': esto se aplica correctamente a otros protocolos, como' ftp: // 'y' mailto: // '. '2': Esto se aplica correctamente con' username' y 'password'. Estos campos opcionales están separados por dos puntos, al igual que el nombre de host y el puerto, y hará tropezar con la mayoría de las otras expresiones regulares que he visto. @ RémyDAVID La cadena de consulta tampoco es analizada normalmente por el objeto 'ubicación' del navegador. Si necesita analizar la cadena de consulta, eche un vistazo a mi pequeña biblioteca para eso: [uqs] (https://npmjs.com/package/uqs). –

2

I como la expresión regular que se publicó en "Javascript: The Good Parts". No es demasiado corto ni demasiado complejo. Esta página en github también tiene el código JavaScript que la usa. Pero es una adaptación para cualquier idioma. https://gist.github.com/voodooGQ/4057330

0
String s = "https://www.thomas-bayer.com/axis2/services/BLZService?wsdl"; 

String regex = "(^http.?://)(.*?)([/\\?]{1,})(.*)"; 

System.out.println("1: " + s.replaceAll(regex, "$1")); 
System.out.println("2: " + s.replaceAll(regex, "$2")); 
System.out.println("3: " + s.replaceAll(regex, "$3")); 
System.out.println("4: " + s.replaceAll(regex, "$4")); 

proporcionará el resultado siguiente:
1: https: //
2: www.thomas-bayer.com
3:/
4:? Axis2/services/BLZService WSDL

Si cambia la URL a
Cadena s = "https://www.thomas-bayer.com?wsdl=qwerwer&ttt=888"; la salida será la siguiente:
1: https: //
2: www.thomas-bayer.com
3:?
4: WSDL = qwerwer & ttt = 888

disfrutar ..
Yosi Lev

0

La expresión regular para hacer el análisis sintáctico completo es bastante horrible.He incluido referencias hacia atrás con nombre para la legibilidad y roto cada parte en líneas separadas, pero todavía se ve así:

^(?:(?P<protocol>\w+(?=:\/\/))(?::\/\/))? 
(?:(?P<host>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^\/?#:]+)(?::(?P<port>[0-9]+))?)\/)? 
(?:(?P<path>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)\/)? 
(?P<file>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+) 
(?:\?(?P<querystring>(?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^#])+))? 
(?:#(?P<fragment>.*))?$ 

Lo que requiere que sea tan detallado es que, salvo por el protocolo o el puerto, cualquiera de las partes puede contener entidades HTML, lo que hace que la delineación del fragmento sea bastante complicada. Por lo tanto, en los últimos casos: el host, la ruta, el archivo, la cadena de consulta y el fragmento, permitimos cualquier entidad html o cualquier carácter que no sea ? o #. La expresión regular para una entidad HTML se parece a esto:

$htmlentity = "&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);" 

Cuando eso se extrae (he usado una sintaxis bigote para representarla), se vuelve un poco más legible:

^(?:(?P<protocol>(?:ht|f)tps?|\w+(?=:\/\/))(?::\/\/))? 
(?:(?P<host>(?:{{htmlentity}}|[^\/?#:])+(?::(?P<port>[0-9]+))?)\/)? 
(?:(?P<path>(?:{{htmlentity}}|[^?#])+)\/)? 
(?P<file>(?:{{htmlentity}}|[^?#])+) 
(?:\?(?P<querystring>(?:{{htmlentity}};|[^#])+))? 
(?:#(?P<fragment>.*))?$ 

En JavaScript, de por supuesto, no se puede utilizar el nombre de referencias hacia atrás, por lo que se convierte en la expresión regular

^(?:(\w+(?=:\/\/))(?::\/\/))?(?:((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^\/?#:]+)(?::([0-9]+))?)\/)?(?:((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)\/)?((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^?#])+)(?:\?((?:(?:&(?:amp|apos|gt|lt|nbsp|quot|bull|hellip|[lr][ds]quo|[mn]dash|permil|\#[1-9][0-9]{1,3}|[A-Za-z][0-9A-Za-z]+);)|[^#])+))?(?:#(.*))?$ 

y en cada partido, el protocolo es \1, el anfitrión es \2, el puerto es \3, la ruta \4, el archivo \5, la querystring \6 y el fragmento \7.

0

He probado unos cuantos de ellos que no cubría mis necesidades, sobre todo la más votos que no coger una url sin una ruta (http://example.com/)

también carecen de nombres de grupo hecho inutilizable de ansible (o quizás mis habilidades de jinja2 faltan).

por lo que esta es mi versión ligeramente modificada con la fuente de ser el más votado versión aquí:

^((?P<protocol>http[s]?|ftp):\/)?\/?(?P<host>[^:\/\s]+)(?P<path>((\/\w+)*\/)([\w\-\.]+[^#?\s]+))*(.*)?(#[\w\-]+)?$ 
-1
//USING REGEX 
/** 
* Parse URL to get information 
* 
* @param url  the URL string to parse 
* @return parsed the URL parsed or null 
*/ 
var UrlParser = function (url) { 
    "use strict"; 

    var regx = /^(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/, 
     matches = regx.exec(url), 
     parser = null; 

    if (null !== matches) { 
     parser = { 
      href    : matches[0], 
      withoutHash  : matches[1], 
      url    : matches[2], 
      origin   : matches[3], 
      protocol   : matches[4], 
      protocolseparator : matches[5], 
      credhost   : matches[6], 
      cred    : matches[7], 
      user    : matches[8], 
      pass    : matches[9], 
      host    : matches[10], 
      hostname   : matches[11], 
      port    : matches[12], 
      pathname   : matches[13], 
      segment1   : matches[14], 
      segment2   : matches[15], 
      search   : matches[16], 
      hash    : matches[17] 
     }; 
    } 

    return parser; 
}; 

var parsedURL=UrlParser(url); 
console.log(parsedURL); 
Cuestiones relacionadas