validar regulares online numeros expresiones especiales ejemplos contraseña caracteres javascript regex

regulares - ¿Cómo accedes a los grupos emparejados en una expresión regular de JavaScript?



validar contraseña javascript expresiones regulares (13)

Quiero hacer coincidir una parte de una cadena usando una expresión regular y luego acceder a esa subcadena entre paréntesis:

var myString = "something format_abc"; // I want "abc" var arr = /(?:^|/s)format_(.*?)(?:/s|$)/.exec(myString); console.log(arr); // Prints: [" format_abc", "abc"] .. so far so good. console.log(arr[1]); // Prints: undefined (???) console.log(arr[0]); // Prints: format_undefined (!!!)

¿Qué estoy haciendo mal?

Descubrí que no había nada malo con el código de expresión regular anterior: la cadena real con la que estaba probando era la siguiente:

"date format_%A"

Informar que "% A" no está definido parece ser un comportamiento muy extraño, pero no está directamente relacionado con esta pregunta, así que abrí una nueva. ¿Por qué una subcadena coincidente devuelve "indefinida" en JavaScript? .

El problema era que console.log toma sus parámetros como una declaración printf , y como la cadena que estaba registrando ( "%A" ) tenía un valor especial, estaba tratando de encontrar el valor del siguiente parámetro.


Terminología utilizada en esta respuesta:

  • La coincidencia indica el resultado de ejecutar su patrón RegEx contra su cadena de esta manera: someString.match(regexPattern) .
  • Los patrones coincidentes indican todas las partes coincidentes de la cadena de entrada, que residen dentro de la matriz de coincidencia . Estas son todas las instancias de su patrón dentro de la cadena de entrada.
  • Los grupos emparejados indican todos los grupos a capturar, definidos en el patrón RegEx. (Los patrones dentro de paréntesis, así: /format_(.*?)/g , donde (.*?) Sería un grupo emparejado. Estos residen dentro de patrones emparejados .

Descripción

Para obtener acceso a los grupos coincidentes , en cada uno de los patrones coincidentes , necesita una función o algo similar para iterar sobre la coincidencia . Hay varias formas de hacerlo, como muestran muchas de las otras respuestas. La mayoría de las otras respuestas usan un bucle while para iterar sobre todos los patrones emparejados , pero creo que todos conocemos los peligros potenciales con ese enfoque. Es necesario hacer coincidir con un new RegExp() lugar de solo el patrón en sí, que solo se mencionó en un comentario. Esto se debe a que el método .exec() se comporta de manera similar a la función de un generador : se detiene cada vez que hay una coincidencia , pero mantiene su .lastIndex para continuar desde allí en la próxima llamada .exec() .

Ejemplos de código

A continuación se muestra un ejemplo de una función searchString que devuelve una Array de todos los patrones coincidentes , donde cada match es una Array con todos los grupos coincidentes que contienen. En lugar de usar un bucle while, proporcioné ejemplos utilizando tanto la función Array.prototype.map() como una forma más eficaz, utilizando un plano for -loop.

Versiones concisas (menos código, más azúcar sintáctica)

Estos son de menor rendimiento, ya que básicamente implementan un forEach -loop en lugar del más rápido for -loop.

// Concise ES6/ES2015 syntax const searchString = (string, pattern) => string .match(new RegExp(pattern.source, pattern.flags)) .map(match => new RegExp(pattern.source, pattern.flags) .exec(match)); // Or if you will, with ES5 syntax function searchString(string, pattern) { return string .match(new RegExp(pattern.source, pattern.flags)) .map(match => new RegExp(pattern.source, pattern.flags) .exec(match)); } let string = "something format_abc", pattern = /(?:^|/s)format_(.*?)(?:/s|$)/; let result = searchString(string, pattern); // [[" format_abc", "abc"], null] // The trailing `null` disappears if you add the `global` flag

Versiones Performant (más código, menos azúcar sintáctica)

// Performant ES6/ES2015 syntax const searchString = (string, pattern) => { let result = []; const matches = string.match(new RegExp(pattern.source, pattern.flags)); for (let i = 0; i < matches.length; i++) { result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i])); } return result; }; // Same thing, but with ES5 syntax function searchString(string, pattern) { var result = []; var matches = string.match(new RegExp(pattern.source, pattern.flags)); for (var i = 0; i < matches.length; i++) { result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i])); } return result; } let string = "something format_abc", pattern = /(?:^|/s)format_(.*?)(?:/s|$)/; let result = searchString(string, pattern); // [[" format_abc", "abc"], null] // The trailing `null` disappears if you add the `global` flag

Todavía tengo que comparar estas alternativas con las mencionadas anteriormente en las otras respuestas, pero dudo que este enfoque sea menos eficaz y menos a prueba de fallos que los otros.


¡No hay necesidad de invocar el método exec ! Puedes usar el método de "coincidencia" directamente en la cadena. Simplemente no te olvides de los paréntesis.

var str = "This is cool"; var matches = str.match(/(This is)( cool)$/); console.log( JSON.stringify(matches) ); // will print ["This is cool","This is"," cool"] or something like that...

La posición 0 tiene una cadena con todos los resultados. La posición 1 tiene la primera coincidencia representada por paréntesis, y la posición 2 tiene la segunda coincidencia aislada entre paréntesis. Los paréntesis anidados son difíciles, así que ten cuidado!


Aquí hay un método que puede usar para obtener el n ° grupo de captura para cada coincidencia:

function getMatches(string, regex, index) { index || (index = 1); // default to the first capturing group var matches = []; var match; while (match = regex.exec(string)) { matches.push(match[index]); } return matches; } // Example : var myString = ''something format_abc something format_def something format_ghi''; var myRegEx = /(?:^|/s)format_(.*?)(?:/s|$)/g; // Get an array containing the first capturing group for every match var matches = getMatches(myString, myRegEx, 1); // Log results document.write(matches.length + '' matches found: '' + JSON.stringify(matches)) console.log(matches);


En lo que respecta a los ejemplos de paréntesis de múltiples coincidencias anteriores, estaba buscando una respuesta aquí después de no obtener lo que quería de:

var matches = mystring.match(/(?:neededToMatchButNotWantedInResult)(matchWanted)/igm);

Después de ver las llamadas de función ligeramente complicadas con while y .push () arriba, me di cuenta de que el problema se puede resolver de manera muy elegante con mystring.replace () en su lugar (la sustitución NO es el punto, y ni siquiera está terminado , la opción de llamada de función recursiva integrada LIMPIA para el segundo parámetro es!):

var yourstring = ''something format_abc something format_def something format_ghi''; var matches = []; yourstring.replace(/format_([^/s]+)/igm, function(m, p1){ matches.push(p1); } );

Después de esto, no creo que vaya a usar .match () para casi nada nunca más.


Por último, pero no menos importante, encontré ese código de una línea que funcionó bien para mí (JS ES6):

var reg = /#([/S]+)/igm; //get hashtags var string = ''mi alegría es total! ✌🙌/n#fiestasdefindeaño #PadreHijo #buenosmomentos #france #paris''; var matches = (string.match(reg) || []).map(e => e.replace(reg, ''$1'')); console.log(matches);

esto volverá: [fiestasdefindeaño, PadreHijo, buenosmomentos, france, paris]


Puede acceder a grupos de captura como este:

var myString = "something format_abc"; var myRegexp = /(?:^|/s)format_(.*?)(?:/s|$)/g; var match = myRegexp.exec(myString); console.log(match[1]); // abc

Y si hay varias coincidencias puedes iterar sobre ellas:

var myString = "something format_abc"; var myRegexp = /(?:^|/s)format_(.*?)(?:/s|$)/g; match = myRegexp.exec(myString); while (match != null) { // matched text: match[0] // match start: match.index // capturing group n: match[n] console.log(match[0]) match = myRegexp.exec(myString); }


Su código funciona para mí (FF3 en Mac), incluso si estoy de acuerdo con que la expresión regular debería ser:

//bformat_(.*?)/b/

(Pero, por supuesto, no estoy seguro porque no conozco el contexto de la expresión regular).


Su sintaxis probablemente no es la mejor para mantener. FF / Gecko define RegExp como una extensión de la función.
(FF2 llegó tan lejos como typeof(/pattern/) == ''function'' )

Parece que esto es específico de FF: IE, Opera y Chrome. Todos lanzan excepciones para ello.

En su lugar, use cualquiera de los métodos mencionados anteriormente por otros: RegExp#exec o String#match .
Ofrecen los mismos resultados:

var regex = /(?:^|/s)format_(.*?)(?:/s|$)/; var input = "something format_abc"; regex(input); //=> [" format_abc", "abc"] regex.exec(input); //=> [" format_abc", "abc"] input.match(regex); //=> [" format_abc", "abc"]


Un trazador de líneas que es práctico solo si tiene un par de paréntesis:

while ( ( match = myRegex.exec( myStr ) ) && matches.push( match[1] ) ) {};


Usando su código:

console.log(arr[1]); // prints: abc console.log(arr[0]); // prints: format_abc

Edición: Safari 3, si importa.


function getMatches(string, regex, index) { index || (index = 1); // default to the first capturing group var matches = []; var match; while (match = regex.exec(string)) { matches.push(match[index]); } return matches; } // Example : var myString = ''Rs.200 is Debited to A/c ...2031 on 02-12-14 20:05:49 (Clear Bal Rs.66248.77) AT ATM. TollFree 1800223344 18001024455 (6am-10pm)''; var myRegEx = /clear bal.+?(/d+/.?/d{2})/gi; // Get an array containing the first capturing group for every match var matches = getMatches(myString, myRegEx, 1); // Log results document.write(matches.length + '' matches found: '' + JSON.stringify(matches)) console.log(matches);

function getMatches(string, regex, index) { index || (index = 1); // default to the first capturing group var matches = []; var match; while (match = regex.exec(string)) { matches.push(match[index]); } return matches; } // Example : var myString = ''something format_abc something format_def something format_ghi''; var myRegEx = /(?:^|/s)format_(.*?)(?:/s|$)/g; // Get an array containing the first capturing group for every match var matches = getMatches(myString, myRegEx, 1); // Log results document.write(matches.length + '' matches found: '' + JSON.stringify(matches)) console.log(matches);


var myString = "something format_abc"; var arr = myString.match(//bformat_(.*?)/b/); console.log(arr[0] + " " + arr[1]);

El /b no es exactamente lo mismo. (Funciona en --format_foo/ , pero no funciona en format_a_b ) Pero quería mostrar una alternativa a tu expresión, lo cual está bien. Por supuesto, la llamada de match es lo importante.


/*Regex function for extracting object from "window.location.search" string. */ var search = "?a=3&b=4&c=7"; // Example search string var getSearchObj = function (searchString) { var match, key, value, obj = {}; var pattern = /(/w+)=(/w+)/g; var search = searchString.substr(1); // Remove ''?'' while (match = pattern.exec(search)) { obj[match[0].split(''='')[0]] = match[0].split(''='')[1]; } return obj; }; console.log(getSearchObj(search));