2009-12-31 8 views
12

Cuando escribo una expresión regular como:¿Cómo se encuentran los índices de los grupos en las expresiones regulares de JavaScript?

var m = /(s+).*?(l)[^l]*?(o+)/.exec("this is hello to you"); 
console.log(m); 

me sale un objeto partido que contenga lo siguiente:

{ 
    0: "s is hello", 
    1: "s", 
    2: "l", 
    3: "o", 
    index: 3, 
    input: "this is hello to you" 
} 

Sé el índice de todo el partido de la propiedad index, pero también necesito para saber el inicio y el final de los grupos combinados. Usar una búsqueda simple no funcionará. En este ejemplo, encontrará la primera 'l' en lugar de la que se encuentra en el grupo.

¿Hay alguna forma de obtener el desplazamiento de un grupo coincidente?

+0

Posible duplicado de [Obtener índice de cada captura en una expresión regular de JavaScript] (http://stackoverflow.com/questions/15934353/get-index-of-each-capture-in-a-javascript-regex) – Vanuan

Respuesta

13

No se puede obtener directamente el índice de un grupo coincidente. Lo que tienes que hacer es poner primero todos los personajes en un grupo partido, incluso los que no les importa:

var m= /(s+)(.*?)(l)([^l]*?)(o+)/.exec('this is hello to you'); 

Ahora tienes todo el partido en partes:

['s is hello', 's', ' is hel', 'l', '', 'o'] 

por lo que puede sumar las longitudes de las cuerdas antes de su grupo para obtener el desplazamiento del índice de coincidencia con el índice del grupo:

function indexOfGroup(match, n) { 
    var ix= match.index; 
    for (var i= 1; i<n; i++) 
     ix+= match[i].length; 
    return ix; 
} 

console.log(indexOfGroup(m, 3)); // 11 
+0

Nice solución. Pero en mi caso necesito agregar los paréntesis adicionales automáticamente. Y corrija las referencias posteriores si alguno + recuerda los números del grupo original. Es para un marcador de sintaxis con coincidencia de alcance, y la solución actual es usar el resaltador halfdone para analizar la sintaxis de la expresión regular + luego hacer todo tipo de cosas en el árbol de sintaxis abstracta. Me encantaría una solución más simple que incorporar las 300 líneas de código. –

+0

Requiere modificación de las expresiones regulares oryginal – pie6k

8

me escribió un simple (y la inicialización de un poco de hinchazón) Javascript a objeto de resolver esta problema en un proyecto en el que he estado trabajando recientemente. Funciona de la misma manera que la respuesta aceptada pero genera la nueva expresión regular y extrae los datos que solicitó automáticamente.

var exp = new MultiRegExp(/(firstBit\w+)this text is ignored(optionalBit)?/i); 
var value = exp.exec("firstbitWithMorethis text is ignored"); 

value = {0: {index: 0, text: 'firstbitWithMore'}, 
     1: null}; 

Git Repo: My MultiRegExp. Espero que esto ayude a alguien por ahí.

edición de agosto de 2015:

Me Try: MultiRegExp Live.

1

Otra clase javascript que también es capaz de analizar grupos anidados está disponible bajo: https://github.com/valorize/MultiRegExp2

Uso:

let regex = /a(?:)bc(def(ghi)xyz)/g; 
let regex2 = new MultiRegExp2(regex); 

let matches = regex2.execForAllGroups('ababa bcdefghixyzXXXX')); 

Will output: 
[ { match: 'defghixyz', start: 8, end: 17 }, 
    { match: 'ghi', start: 11, end: 14 } ] 
+0

se ve bien, pero creo que es mejor añadir una función de generador, en alguna situación sin necesidad de obtener todos los grupos. – Mithril

+0

@Mithril podría usted explicar lo que piensa de en https://github.com/valorize/MultiRegExp2/issues/5? – velop

0

Basado en la ecma regular expression syntax He escrito un analizador respectivo una extensión de la clase RegExp lo cual resuelve además de este problema (método de índice completamente indexado) así como otras limitaciones de la implementación de JavaScript RegExp, por ejemplo: búsqueda basada en el grupo & reemplazar. Puede test and download the implementation here (también está disponible como módulo NPM).

La aplicación funciona de la siguiente manera (pequeño ejemplo):

//Retrieve content and position of: opening-, closing tags and body content for: non-nested html-tags. 
var pattern = '(<([^ >]+)[^>]*>)([^<]*)(<\\/\\2>)'; 
var str = '<html><code class="html plain">first</code><div class="content">second</div></html>'; 
var regex = new Regex(pattern, 'g'); 
var result = regex.exec(str); 

console.log(5 === result.length); 
console.log('<code class="html plain">first</code>'=== result[0]); 
console.log('<code class="html plain">'=== result[1]); 
console.log('first'=== result[3]); 
console.log('</code>'=== result[4]); 
console.log(5=== result.index.length); 
console.log(6=== result.index[0]); 
console.log(6=== result.index[1]); 
console.log(31=== result.index[3]); 
console.log(36=== result.index[4]); 

Probé así la implementación de @velop pero la aplicación con errores, por ejemplo, parece que no maneja correctamente referencias hacia atrás, por ejemplo, "/ a (?:) bc (def (\ 1 ghi) xyz)/g" - cuando se agrega paranthesis al frente, la retro-referencia \ 1 necesita incrementarse en consecuencia (que no es el caso en su implementación) .

+0

por favor use la descripción de cómo está trabajando su herramienta. A veces es peligroso descargar desde espacios desconocidos. – Alexan

Cuestiones relacionadas