2012-01-08 28 views
5

Estoy tratando de entender esta expresión regular, ¿me pueden ayudar?regex que no entiendo

(?s)\\{\\{wotd\\|(.+?)\\|(.+?)\\|([^#\\|]+).*?\\}\\} 
  • yo no entiendo muy bien el significado de dotall: (?s)
  • por qué el doble \\ antes }?
  • ¿qué significa esto exactamente: (.+?) (debemos leer esto como: la ., entonces + que actúa sobre el ., entonces ? responder al resultado de .+
+4

En la fuente donde se ve esto, es que en una cadena literal ? Por ejemplo, ¿es realmente 'Patrón p = Pattern.compile (" (? S) \\ {\\ {wotd \\ | (. +?) \\ | (¿+?) \\ | ([^ # \\ |] +). *? \\} \\} ");'? Importa, porque las barras invertidas son escapes tanto en cadenas literales como en expresiones regulares, por lo que para interpretar '\\ {' necesitamos saber si eso es '" \\ {"' (en cuyo caso '' \\ 'es visto por el compilador de patrones como una barra diagonal inversa que escapa del siguiente '{') o es '\\ {' (por ejemplo, leer de un archivo de texto o algo así), en cuyo caso el compilador de patrones ve una reacción * escapada * seguida de un ' {'. –

+0

'. +?' Es un operador no codicioso ("renuente") '+'. '\\\' significa una barra invertida literal, suponiendo que la expresión regular es Java y está incrustada en una cadena de Java, la primera '\\' se escapa de la segunda. –

Respuesta

8

Esta expresión regular es de una cadena El?. "canonical" regex es:

modificador
(?s)\{\{wotd\|(.+?)\|(.+?)\|([^#\|]+).*?\}\} 

el dotall significa que el punto también puede coincidir con un carácter de nueva línea, pero también lo puede complementado clases de caracteres, al menos con Java: es decir, [^a] voluntad empareja cada carácter que no es a, nueva línea incluida. Sin embargo, algunos motores de expresiones regulares NO coinciden con una nueva línea en clases de caracteres complementadas (esto se puede considerar como un error).

El +? y *? son cuantificadores perezosos (que generalmente se deben evitar). Significa que tendrán que mirar hacia adelante antes de cada personaje que quieran tragar para ver si este personaje puede satisfacer el siguiente componente de una expresión regular.

El hecho de que { y } están precedidos con \ se debe a {...} es el cuantificador de repetición {n, m} donde n y m son números enteros.

Además, es inútil escapar de la tubería | en la clase de caracteres [^#\|], simplemente puede escribirse como [^#|].

Y finalmente, .*? al final parece tragarse el resto de los campos. Una mejor alternativa es utilizar el patrón normal* (special normal*)*, donde normal es [^|}] y special es \|.

Aquí está la expresión regular sin usar cuantificadores perezosos, la clase de caracteres "fija" y el extremo modificado. Tenga en cuenta que el modificador dotall ha desaparecido, así, ya que el punto ya no se utiliza:

\{\{wotd\|([^|]+)\|([^|]+)\|([^#|]+)[^|}]*(?:\|[^|}]*)*\}\} 

Paso a paso:

\{\{   # literal "{{", followed by 
wotd   # literal "wotd", followed by 
\|   # literal "|", followed by 
([^|]+)  # one or more characters which are not a "|" (captured), followed by 
\|   # literal "|", followed by 
([^|]+)  # one or more characters which are not a "|" (captured), followed by 
\|   # literal "|", followed by 
([^#|]+)  # one or more characters which are not "|" or "#", followed by 
[^|}]*  # zero or more characters which are not "|" or "}", followed by 
(?:   # begin group 
    \|   # a literal "|", followed by 
    [^|}]*  # zero or more characters which are not "|" or "}" 
)   # end group 
*   # zero or more times, followed by 
\}\}   # literal "}}" 
+0

¿Por qué sugerir evitar los cuantificadores perezosos? – Lucero

+0

Cabe señalar que su expresión regular no es equivalente al original; el original coincidirá con muchas cuerdas que el tuyo no tendrá. Si tuviera que adivinar, supongo que su versión está más cerca de la intención original del regex-writer, pero sin saber cuáles eran los requisitos, no hay forma de saberlo con certeza. (Y, por cierto, también podría eliminar '(? S)' de su versión, ya que su versión no usa '.' de todos modos.) – ruakh

+0

No el'. *? 'Final tiene significado porque las otras tuberías también se escapó (que su expresión regular final cae). La expresión regular está buscando una cadena donde la tubería se utiliza como delimitador de campo: '{wotd | field1 | field2 | some_stuff # posiblemente un comentario?}' – user268396