validate test regulares online expresiones example javascript regex

test - ¿Grupos de captura nombrados en JavaScript regex?



javascript regex test (8)

Hasta donde sé, no existe el nombre de grupos de captura en JavaScript. ¿Cuál es la forma alternativa de obtener una funcionalidad similar?


ECMAScript 2018 introduce grupos de captura nombrados en expresiones regulares de JavaScript.

Si necesita admitir navegadores más antiguos, puede hacer todo lo posible con grupos de captura normales (numerados) que puede hacer con grupos de captura nombrados, solo necesita realizar un seguimiento de los números, lo que puede ser engorroso si el orden de captura del grupo en su cambios de expresiones regulares

Solo hay dos ventajas "estructurales" de los grupos de captura nombrados en los que puedo pensar:

  1. 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 ( consulte 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.

  2. 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. Supongamos que desea agregar un cero a un dígito y, por lo tanto, desea reemplazar (/d) con $10 . En JavaScript, esto funcionará (siempre y cuando tenga menos de 10 grupos de captura en su expresión regular), pero Perl pensará que está buscando la referencia inversa número 10 lugar del número 1 , seguido por un 0 . En Perl, puede usar ${1}0 en este caso.

Aparte de eso, los grupos de captura nombrados son solo "azúcar sintáctico". Ayuda utilizar grupos de captura solo cuando realmente los necesita y para usar grupos que no capturan (?:...) en todas las demás circunstancias.

El problema más grande (en mi opinión) con JavaScript es que no admite expresiones regulares que harían mucho más fácil la creación de expresiones regulares legibles y complejas.

La biblioteca XRegExp de Steve Levithan resuelve estos problemas.


En ES6 puedes utilizar la desestructuración de arrays para capturar tus grupos:

let text = ''27 months''; let regex = /(/d+)/s*(days?|months?|years?)/; let [, count, unit] = text.match(regex) || []; // count === ''27'' // unit === ''months''

Darse cuenta:

  • la primera coma en la última omite el primer valor de la matriz resultante, que es la cadena completa
  • el || [] || [] después de .match() evitará un error de desestructuración cuando no haya coincidencias (porque .match() devolverá null )

Hay una biblioteca node.js llamada named-regexp que puede usar en sus proyectos node.js (en el navegador empaquetando 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 la apertura de las llaves de captura en su expresión regular, puede crear una asignación entre los grupos de captura nombrados y los grupos de captura numerados en su expresión regular y puede mezclar y combinar libremente. Solo tiene que eliminar los nombres de grupo antes de usar la expresión regular. He escrito tres funciones que demuestran eso. Vea esta esencia: https://gist.github.com/gbirke/2cc2370135b665eee3ef


Los grupos de captura nombrados podrían hacerlo en JavaScript muy pronto.
La propuesta ya está en la etapa 3.

A un grupo de captura se le puede asignar un nombre usando la sintaxis (? ...) para cualquier nombre de identificador. La expresión regular para una fecha se puede escribir como / (? / D {4}) - (? / D {2}) - (? / 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 grupo del resultado de expresión regular. También se crean referencias numeradas a los grupos, al igual que para los grupos no nombrados. Por ejemplo:

let re = /(?<year>/d{4})-(?<month>/d{2})-(?<day>/d{2})/u; let result = re.exec(''2015-01-02''); // result.groups.year === ''2015''; // result.groups.month === ''01''; // result.groups.day === ''02''; // result[0] === ''2015-01-02''; // result[1] === ''2015''; // result[2] === ''01''; // result[3] === ''02'';


Nombrar grupos capturados proporciona una cosa: menos confusión con expresiones regulares complejas.

Realmente depende de tu caso de uso, pero tal vez imprimir tu expresión regular podría ser útil.

O podría intentar y definir constantes para referirse a sus grupos capturados.

Los comentarios también pueden ayudar a mostrar a otros que leen tu código, lo que has hecho.

Por lo demás, debo estar de acuerdo con la respuesta de Tims.


Otra posible solución: crear un objeto que contenga los nombres e índices de grupo.

var regex = new RegExp("(.*) (.*)"); var regexGroups = { FirstName: 1, LastName: 2 };

Luego, use las teclas de objeto para hacer referencia a los grupos:

var m = regex.exec("John Smith"); var f = m[regexGroups.FirstName];

Esto mejora la legibilidad / calidad del código utilizando los resultados de la expresión regular, pero no la legibilidad de la expresión regular.


Puede usar XRegExp , una implementación de expresiones regulares multiproveedor , extensible y aumentada, que incluye soporte para sintaxis, indicadores y métodos adicionales:

  • Agrega nueva sintaxis de texto regex y de reemplazo, incluida la compatibilidad completa para la captura con nombre .
  • Agrega dos nuevos indicadores regex: s , para hacer que dot coincida con todos los caracteres (también conocido como dotall o modo de línea simple), x , para espacios libres y comentarios (también conocido como modo extendido).
  • Proporciona un conjunto de funciones y métodos que hacen que el complejo procesamiento de expresiones regulares sea muy fácil.
  • Resuelve automáticamente las incoherencias cruzadas entre navegadores más comunes en el comportamiento y la sintaxis de expresiones regulares.
  • Le permite crear y usar fácilmente complementos que agregan nueva sintaxis y banderas al lenguaje de expresiones regulares de XRegExp.

Si bien no puedes hacer esto con JavaScript simple, tal vez puedas usar alguna función Array.prototype.reduce como Array.prototype.reduce para convertir las coincidencias indexadas en nombres usando magia .

Obviamente, la siguiente solución necesitará que las coincidencias ocurran en orden:

// @text Contains the text to match // @regex A regular expression object (f.e. /.+/) // @matchNames An array of literal strings where each item // is the name of each group function namedRegexMatch(text, regex, matchNames) { var matches = regex.exec(text); return matches.reduce(function(result, match, index) { if (index > 0) // This substraction is required because we count // match indexes from 1, because 0 is the entire matched string result[matchNames[index - 1]] = match; return result; }, {}); } var myString = "Hello Alex, I am John"; var namedMatches = namedRegexMatch( myString, /Hello ([a-z]+), I am ([a-z]+)/i, ["firstPersonName", "secondPersonName"] ); alert(JSON.stringify(namedMatches));