Estoy tratando de analizar el siguiente tipo de cadena:
[key:"val" key2:"val2"]
donde hay clave arbitraria: pares "val" dentro. Quiero tomar el nombre de la clave y el valor. Para aquellos curiosos, estoy tratando de analizar el formato de base de datos de task warrior.
Aquí está mi cadena de prueba:
[description:"aoeu" uuid:"123sth"]
lo que pretende resaltar que cualquier cosa puede estar en una clave o valor aparte del espacio, sin espacios alrededor de los dos puntos, y los valores siempre están entre comillas dobles.
En el nodo, esta es mi salida:
[deuteronomy][gatlin][~]$ node
> var re = /^\[(?:(.+?):"(.+?)"\s*)+\]$/g
> re.exec('[description:"aoeu" uuid:"123sth"]');
[ '[description:"aoeu" uuid:"123sth"]',
'uuid',
'123sth',
index: 0,
input: '[description:"aoeu" uuid:"123sth"]' ]
Pero description:"aoeu"
también coincide con este patrón. ¿Cómo puedo recuperar todos los partidos?
javascript
regex
regex-group
taskwarrior
Gatlin
fuente
fuente
"some string".match(/regex/g)
Respuestas:
Continúa llamando
re.exec(s)
en un bucle para obtener todas las coincidencias:Pruébelo con este JSFiddle: https://jsfiddle.net/7yS2V/
fuente
while
lugar dedo … while
?while(m = re.exec(s))
, que es un IMO antipatrón, o tienes que escribirm = re.exec(s); while (m) { ... m = re.exec(s); }
. Prefiero eldo ... if ... while
idioma, pero otras técnicas también funcionarían.g
configurado el indicador; de lo contrario, el puntero interno no se moverá hacia adelante. Doc .str.match(pattern)
, sipattern
tiene el indicador globalg
, devolverá todas las coincidencias como una matriz.Por ejemplo:
fuente
"All of us except @Emran:emran26, @Raju:raju13 and @Noman:noman42".match(/@(\w+):(\w+)/g)
(que volverán["@Emran:emran26", "@Raju:raju13", "@Noman:noman42"]
)/@\w/g
onew RegExp("@\\w", "g")
Para recorrer todas las coincidencias, puede usar la
replace
función:fuente
Esta es una solucion
Esto se basa en la respuesta de lawnsea, pero más breve.
Tenga en cuenta que la bandera 'g' debe estar configurada para mover el puntero interno hacia adelante a través de invocaciones.
fuente
devuelve todas las coincidencias como una matriz.
Si, por alguna razón misteriosa, necesita la información adicional que viene
exec
, como alternativa a las respuestas anteriores, puede hacerlo con una función recursiva en lugar de un bucle de la siguiente manera (que también se ve mejor).Como se indicó en los comentarios anteriores, es importante tener
g
al final de la definición de expresiones regulares para mover el puntero hacia adelante en cada ejecución.fuente
Finalmente comenzamos a ver una
matchAll
función incorporada, consulte aquí la descripción y la tabla de compatibilidad . Parece que a partir de mayo de 2020, Chrome, Edge, Firefox y Node.js (12+) son compatibles, pero no IE, Safari y Opera. Parece que fue redactado en diciembre de 2018, así que dedíqueles tiempo para llegar a todos los navegadores, pero confío en que llegue allí.La
matchAll
función incorporada es agradable porque devuelve un iterable . ¡También devuelve grupos de captura para cada partida! Entonces puedes hacer cosas comoTambién parece que cada objeto de coincidencia usa el mismo formato que
match()
. Así, cada objeto es una matriz de los grupos de los partidos y captura, junto con tres propiedades adicionalesindex
,input
, ygroups
. Entonces se ve así:Para obtener más información sobre
matchAll
también hay una página de desarrolladores de Google . También hay polyfills / shims disponibles.fuente
Basado en la función de Agus, pero prefiero devolver solo los valores coincidentes:
fuente
Los Iterables son más bonitos:
Uso en un bucle:
O si quieres una matriz:
fuente
if (m)
should beif (match)
matchAll
Si tienes ES9
(Es decir, si su sistema: Chrome, Node.js, Firefox, etc. admite Ecmascript 2019 o posterior)
Use el nuevo
yourString.matchAll( /your-regex/ )
.Si no tienes ES9
Si tiene un sistema anterior, aquí hay una función para copiar y pegar fácilmente
ejemplo de uso:
salidas:
fuente
Aquí está mi función para obtener los partidos:
fuente
Desde ES9, ahora hay una manera mejor y más simple de obtener todas las coincidencias, junto con información sobre los grupos de captura y su índice:
Actualmente es compatible con Chrome, Firefox, Opera. Dependiendo de cuándo lea esto, consulte este enlace para ver su soporte actual.
fuente
g
ylastIndex
debe restablecerse a 0 antes de la invocación dematchAll
.Utilizar este...
Devolverá una serie de todas las coincidencias ... Eso funcionaría bien ... Pero recuerde que no tendrá en cuenta a los grupos ... Solo devolverá las coincidencias completas ...
fuente
Definitivamente recomendaría usar la función String.match () y crear un RegEx relevante para ello. Mi ejemplo es con una lista de cadenas, que a menudo es necesaria al escanear entradas de usuario para palabras clave y frases.
¡Espero que esto ayude!
fuente
Esto realmente no va a ayudar con su problema más complejo, pero lo estoy publicando de todos modos porque es una solución simple para las personas que no están haciendo una búsqueda global como usted.
He simplificado la expresión regular en la respuesta para que sea más clara (esto no es una solución a su problema exacto).
Eso se ve más detallado de lo que es debido a los comentarios, así es como se ve sin comentarios
Tenga en cuenta que los grupos que no coincidan se enumerarán en la matriz como
undefined
valores.Esta solución utiliza el operador de propagación ES6 para purificar la matriz de valores específicos de expresiones regulares. Tendrá que ejecutar su código a través de Babel si desea soporte para IE11.
fuente
Aquí hay una solución de una línea sin un ciclo while .
El orden se conserva en la lista resultante.
Las desventajas potenciales son
fuente
Supongo que si hubiera casos extremos como espacios extra o faltantes, esta expresión con menos límites también podría ser una opción:
Prueba
Circuito RegEx
jex.im visualiza expresiones regulares:
fuente
Aquí está mi respuesta:
fuente
str
) tiene el formato incorrecto (demasiados corchetes). Solo captura la clave, no el valor. Su código tiene un error de sintaxis y no se ejecuta (los últimos paréntesis). Si responde una pregunta "antigua" con una respuesta ya aceptada, asegúrese de agregar más conocimiento y una mejor respuesta que la ya aceptada. No creo que tu respuesta haga eso.