Escribí una rutina de Javascript que, dado un nombre de host o una URL, encuentra el dominio raíz .
function getRootDomain(s){ var sResult = '' try { sResult = s.match(/^(?:.*\:\/?\/)?(?<domain>[\w\-\.]*)/).groups.domain .match(/(?<root>[\w\-]*(\.\w{3,}|\.\w{2}|\.\w{2}\.\w{2}))$/).groups.root; } catch(ignore) {} return sResult; }¿Cuál es la técnica para combinar las dos reglas de expresiones regulares en una regla?
Utilicé este tutorial para tratar de mejorar mi experiencia existente de RegExp a lo largo de los años, aunque nunca entendí realmente mirar hacia atrás y mirar hacia adelante (¿qué podría ser útil aquí?), y luego usé la gran herramienta en RegEx101.com para prueba y error. Lo que intenté fue pegar lo que está después de <root> para reemplazar lo que viene después de <domain> , y variaciones de eso, y todo falló.
Un conjunto de prueba para usar con una herramienta como RegEx101 podría ser:
https://test.com:8080/?id=4&re=3 https://test-test.com:8080/?id=4&re=3 https://data.test.com:8080/?id=4&re=3 https://data.test.com/?id=4&re=3 https://data.test.com/ https://data.test.com#testing https://data.test.com/#testing https://data.test.com:8080/#testing https://data.test.com:8080#testing https://data.tester.com/ https://data-test.test.com/ https://test.com https://test.com#testing https://test.com/ https://test.am/?id=4 https://test.com?id=3&re=3 https://test.com/?id=3&re=3 https://megatest.com/?id=3&re=3 test.com data.test.co.uk test.co data.test.com data.tester-test.com data-test.tester-test.com tester-test.com about:blankLa segunda expresión regular usa la aserción $ para coincidir solo con el final de la captura de .domain .
Sin embargo, la primera RegExp deja de coincidir después del dominio (cuando se encuentra con un / , un ? , un # , un : o el final de la cadena si no hay ruta, cadena de consulta o partes hash. Por lo tanto, no puede simplemente reutilice la aserción $ , fallaría en algunos casos.
Para combinar ambas partes, podría reemplazar la captura de domain con esto:
.*?(?<root>[\w\-]*(\.\w{3,}|\.\w{2}|\.\w{2}\.\w{2}))(?:[\/?#:]|$)
(?:[\/?#]|$) al final es un grupo que no captura que coincide con los caracteres de destino o con el final de la cadena.
.*? combina frugalmente con cualquier cosa. Es decir, primero intenta hacer coincidir la captura root seguida de (?:[\/?#]|$) . Cada vez que falla, come un carácter y vuelve a intentarlo, lo que le permite buscar la root .
También:
puede combinar \.\w{3,}|\.\w{2} en solo \.\w{2,} .
puede usar un grupo que no captura alrededor de los TLD ( (?:...) vs (...) .
Sería mejor usar .*? para obtener el protocolo, o podría terminar englobándose demasiado (con un .* codicioso, pasar https://example.com/#://bar.com devolvería bar.com ).
No necesita escapar de : . En modo Unicode, ese escape es en realidad un error de sintaxis.
resultando en
const x = /^(?:.*?:\/\/)?.*?(?<root>[\w\-]*(?:\.\w{2,}|\.\w{2}\.\w{2}))(?:[\/?#:]|$)/ De hecho, escribí un generador RegExp que puede ayudarlo a avanzar en su viaje de aprendizaje RegExp... Aquí está su RegExp portado a compose-regexp