Hasta donde yo sé, no hay grupos de captura con nombre en JavaScript. ¿Cuál es la forma alternativa de obtener una funcionalidad similar?
javascript
regex
mmierins
fuente
fuente
Respuestas:
ECMAScript 2018 introduce grupos de captura con nombre en expresiones regulares de JavaScript.
Ejemplo:
Si necesita admitir navegadores antiguos, puede hacer todo con grupos de captura normales (numerados) que puede hacer con grupos de captura con nombre, solo necesita realizar un seguimiento de los números, lo que puede ser engorroso si el orden del grupo de captura en su cambios de expresiones regulares.
Solo se me ocurren dos ventajas "estructurales" de los grupos de captura con nombre:
En algunos sabores de expresiones regulares (.NET y JGSoft, hasta donde yo sé), puede usar el mismo nombre para diferentes grupos en su expresión regular ( vea aquí un ejemplo donde esto importa ). Pero la mayoría de los sabores de expresiones regulares no son compatibles con esta funcionalidad de todos modos.
Si necesita referirse a grupos de captura numerados en una situación en la que están rodeados de dígitos, puede tener un problema. Digamos que desea agregar un cero a un dígito y, por lo tanto, desea reemplazar
(\d)
con$10
. En JavaScript, esto funcionará (siempre que tenga menos de 10 grupos de captura en su expresión regular), pero Perl pensará que está buscando un número de referencia en10
lugar de un número1
, seguido de a0
. En Perl, puede usar${1}0
en este caso.Aparte de eso, los grupos de captura nombrados son simplemente "azúcar sintáctico". Es útil usar grupos de captura solo cuando realmente los necesita y usar grupos sin captura
(?:...)
en todas las demás circunstancias.El mayor problema (en mi opinión) con JavaScript es que no admite expresiones regulares detalladas, lo que facilitaría mucho la creación de expresiones regulares complejas y legibles.
La biblioteca XRegExp de Steve Levithan resuelve estos problemas.
fuente
Puede usar XRegExp , una implementación aumentada, extensible y de navegador cruzado de expresiones regulares, que incluye soporte para sintaxis, indicadores y métodos adicionales:
s
para que el punto coincida con todos los caracteres (también conocido como modo dotall o singleline) yx
para espacios libres y comentarios (también conocido como modo extendido).fuente
Otra posible solución: crear un objeto que contenga los nombres e índices del grupo.
Luego, use las teclas de objeto para hacer referencia a los grupos:
Esto mejora la legibilidad / calidad del código utilizando los resultados de la expresión regular, pero no la legibilidad de la propia expresión regular.
fuente
En ES6 puede usar la desestructuración de matrices para capturar sus grupos:
Aviso:
let
omite el primer valor de la matriz resultante, que es la cadena completa coincidente|| []
after.exec()
evitará un error de desestructuración cuando no haya coincidencias (porque.exec()
volveránull
)fuente
String.prototype.match
devuelve una matriz con: toda la cadena coincidente en la posición 0, luego cualquier grupo después de eso. La primera coma dice "omita el elemento en la posición 0"RegExp.prototype.exec
másString.prototype.match
en lugares donde la cadena puede sernull
oundefined
.Actualización: ¡Finalmente llegó a JavaScript (ECMAScript 2018)!
Los grupos de captura con nombre podrían ingresar a JavaScript muy pronto.
La propuesta está en la etapa 3 ya.
Un grupo de captura puede recibir un nombre dentro de corchetes angulares utilizando la
(?<name>...)
sintaxis, para cualquier nombre de identificador. La expresión regular para una fecha se puede escribir como/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u
. Cada nombre debe ser único y seguir la gramática de ECMAScript IdentifierName .Se puede acceder a los grupos con nombre desde las propiedades de una propiedad de grupos del resultado de la expresión regular. También se crean referencias numeradas a los grupos, al igual que para los grupos sin nombre. Por ejemplo:
fuente
let {year, month, day} = ((result) => ((result) ? result.groups : {}))(re.exec('2015-01-02'));
Nombrar grupos capturados proporciona una cosa: menos confusión con expresiones regulares complejas.
Realmente depende de su caso de uso, pero tal vez la impresión bonita de su expresión regular podría ayudar.
O podría intentar definir constantes para referirse a sus grupos capturados.
Los comentarios también pueden ayudar a mostrar a otros que leen su código, lo que ha hecho.
Por lo demás, debo estar de acuerdo con la respuesta de Tims.
fuente
Hay una biblioteca node.js llamada named-regexp que puede usar en sus proyectos node.js (en el navegador al empaquetar la biblioteca con browserify u otros scripts de empaquetado). Sin embargo, la biblioteca no se puede usar con expresiones regulares que contienen grupos de captura sin nombre.
Si cuenta las llaves de captura de apertura en su expresión regular, puede crear una asignación entre los grupos de captura con nombre y los grupos de captura numerados en su expresión regular y puede mezclar y combinar libremente. Solo tiene que eliminar los nombres de los grupos antes de usar la expresión regular. He escrito tres funciones que demuestran eso. Vea esta esencia: https://gist.github.com/gbirke/2cc2370135b665eee3ef
fuente
Como dijo Tim Pietzcker , ECMAScript 2018 introduce grupos de captura con nombre en expresiones regulares de JavaScript. Pero lo que no encontré en las respuestas anteriores fue cómo usar el grupo capturado nombrado en la expresión regular misma.
puede utilizar un grupo de captura llamado con esta sintaxis:
\k<name>
. por ejemploy como Forivin dijo, puede usar el grupo capturado en el resultado del objeto de la siguiente manera:
fuente
Si bien no puede hacer esto con JavaScript de vainilla, tal vez pueda usar alguna
Array.prototype
función comoArray.prototype.reduce
convertir las coincidencias indexadas en nombradas usando algo de magia .Obviamente, la siguiente solución necesitará que las coincidencias ocurran en orden:
fuente
var assocArray = Regex("hello alex, I am dennis", "hello ({hisName}.+), I am ({yourName}.+)");
RegExp
objeto agregando una función a su prototipo.¿No tienes ECMAScript 2018?
Mi objetivo era hacer que funcionara lo más similar posible a lo que estamos acostumbrados con los grupos con nombre. Mientras que en ECMAScript 2018 puede colocar
?<groupname>
dentro del grupo para indicar un grupo con nombre, en mi solución para javascript anterior, puede colocar(?!=<groupname>)
dentro del grupo para hacer lo mismo. Entonces es un conjunto extra de paréntesis y un extra!=
. ¡Muy cerca!Lo envolví todo en una función de prototipo de cadena
Caracteristicas
Instrucciones
(?!={groupname})
dentro de cada grupo que quieras nombrar()
colocando?:
al principio de ese grupo. Estos no serán nombrados.arrays.js
uso
resultado de o
fuente