2008-11-26 22 views
28

Parece que no puedo encontrar una respuesta a este problema, y ​​me pregunto si existe. Ejemplo simplificado:coincidencias superpuestas en Regex

Considere una cadena "nnnn", donde quiero encontrar todas las coincidencias de "nn", pero también aquellas que se superponen entre sí. Así, el texto proporcionaría los siguientes 3 partidos:

  1. nn nn
  2. n nn n
  3. nn nn

Sé que esto no es exactamente lo expresiones regulares son significado para, pero caminar la cuerda y analizar esto manualmente parece una gran cantidad de código, teniendo en cuenta que en realidad las coincidencias tendrían que hacerse usando un patrón, no una cadena literal. En g.

Respuesta

19

Una posible solución podría ser utilizar un positive look behind:

(?<=n)n 

le daría la posición final:

  1. n * *** ** n nn  
  2. n * n *** n ** n  
  3. nn * n *** n **

Como lo mencionan en Timothy Khouri, una búsqueda positiva hacia delantees más intuitivo

yo preferiría a su proposición (?=nn)n la forma más simple:

(n)(?=(n)) 

Eso sería hacer referencia a la primera posición de las cadenas que desea y capturaría la segunda n en el grupo (2).

Eso es así porque:

  • Cualquier expresión regular válida se puede utilizar dentro de la búsqueda hacia delante.
  • Si contiene paréntesis de captura, las referencias se guardarán.

Así que el grupo (1) y el grupo (2) capturarán lo que 'n' represente (incluso si es una expresión regular complicada).

+2

Además, podría haberlo hecho con una mirada positiva hacia adelante: (? = Nn) n ... que dice "mientras que adelante hay dos N, haga coincidir una N". –

+0

Disculpe, pero todavía no veo las tres capturas superpuestas solicitadas. Capturas dos n, pero no tres grupos. Si hago coincidir (\ d \ d) (? = (\ D \ d)) con foo4237bar, obtengo dos capturas, no tres: 42 y 37 (tanto en Regex Coach como en PCRE Workbench). Probablemente soy grueso, así que necesito más explicaciones. – PhiLho

+0

Lea de nuevo la respuesta: (\ d) (? = (\ D)), no (\ d \ d) (? = (\ D \ d)): tendrá 3 conjuntos de grupos de captura: (4) (2), (2) (3), (3) (7) – VonC

1

AFAIK, no hay una forma pura de regex para hacer eso de una vez (es decir, devolver las tres capturas que solicita sin bucle).

Ahora, puede encontrar un patrón una vez, y recorrer la búsqueda comenzando con desplazamiento (posición encontrada + 1). Debe combinar el uso de expresiones regulares con un código simple.

[EDIT] Genial, estoy votando cuando básicamente dije lo que Jan muestra ...
[EDIT 2] Para ser claro: la respuesta de Jan es mejor. No es más preciso, pero ciertamente más detallado, merece ser elegido. Simplemente no entiendo por qué el mío está degradado, ya que todavía no veo nada incorrecto en él. No es gran cosa, solo molesto.

+0

¡Láncémela por 1 segundo, retiraré mi respuesta idéntica! –

+0

no es verdad, vea la respuesta de "VonC" –

+0

@Timothy: eso no hará la captura, y aún tiene que repetir los resultados, así que no estoy seguro de las ventajas ... – PhiLho

21

Usar un lookahead con un grupo de captura funciona, a expensas de hacer que su expresión regular sea más lenta y más complicada. Una solución alternativa es decirle al método Regex.Match() dónde debe comenzar el siguiente intento de coincidencia. Intente esto:

Regex regexObj = new Regex("nn"); 
Match matchObj = regexObj.Match(subjectString); 
while (matchObj.Success) { 
    matchObj = regexObj.Match(subjectString, matchObj.Index + 1); 
} 
+0

Regular-Expressions.info webmaster ... => obligatorio + 1. Además, tienes razón, por supuesto. – VonC

Cuestiones relacionadas