Pyge expresiones no codiciosas

150

¿Cómo hago una expresión regular de Python como "(.*)"tal, dadas las "a (b) c (d) e"coincidencias de Python en "b"lugar de "b) c (d"?

Sé que puedo usar en "[^)]"lugar de ".", pero estoy buscando una solución más general que mantenga mi expresión regular un poco más limpia. ¿Hay alguna manera de decirle a Python "oye, empareja esto lo antes posible"?

So8res
fuente

Respuestas:

209

Buscas al todopoderoso *?

De los documentos, codiciosos versus no codiciosos

la fase de clasificación no codiciosos *?, +?, ??, o {m,n}?[...] partido tan poco texto como sea posible.

Trey Stout
fuente
De acuerdo con el Archivo de Internet, todo ese enlace apuntaba a una copia de los documentos del módulo "re" de Python, por lo que el enlace de Trey funciona igual de bien.
spiffytech
2
¿Cuál es el nombre común en inglés para esto *??
Trevor Boyd Smith
Personajes comodín @Trevor Boyd Smith
Serge
3
Esto se llama "no codiciosa" calificador
brunetton
65
>>> x = "a (b) c (d) e"
>>> re.search(r"\(.*\)", x).group()
'(b) c (d)'
>>> re.search(r"\(.*?\)", x).group()
'(b)'

Según los documentos :

Los calificadores ' *', ' +' y ' ?' son codiciosos; coinciden con la mayor cantidad de texto posible. Algunas veces este comportamiento no es deseado; si el RE <.*>se compara con " <H1>title</H1>", coincidirá con toda la cadena, y no solo " <H1>". Agregar ' ?' después del calificador hace que realice el partido de manera no codiciosa o mínima; se igualarán la menor cantidad de caracteres posible. El uso .*?en la expresión anterior solo coincidirá ' <H1>'.

Paolo Bergantino
fuente
14

No \\(.*?\\)funcionaria? Esa es la sintaxis no codiciosa.

Zitrax
fuente
5

Como los otros han dicho usando el? El modificador en el cuantificador * resolverá su problema inmediato, pero tenga cuidado, está comenzando a desviarse hacia áreas donde las expresiones regulares dejan de funcionar y necesita un analizador en su lugar. Por ejemplo, la cadena "(foo (bar)) baz" le causará problemas.

Chas Owens
fuente
5

El uso de una coincidencia no greedy es un buen comienzo, pero también te sugiero que reconsideres cualquier uso de .*¿qué pasa con esto?

groups = re.search(r"\([^)]*\)", x)
ojrac
fuente
3

¿Quieres que coincida con "(b)"? Haz lo que Zitrax y Paolo han sugerido. ¿Quieres que coincida con "b"? Hacer

>>> x = "a (b) c (d) e"
>>> re.search(r"\((.*?)\)", x).group(1)
'b'
David Berger
fuente
0

Para empezar, no sugiero usar "*" en expresiones regulares. Sí, lo sé, es el delimitador de caracteres múltiples más utilizado, pero no obstante es una mala idea. Esto se debe a que, si bien coincide con cualquier cantidad de repetición para ese carácter, "any" incluye 0, que generalmente es algo para lo que desea generar un error de sintaxis, no aceptar. En cambio, sugiero usar el +signo, que coincide con cualquier repetición de longitud> 1. Además, por lo que puedo ver, se trata de expresiones entre paréntesis de longitud fija. Como resultado, probablemente pueda usar la {x, y}sintaxis para especificar específicamente la longitud deseada.

Sin embargo, si realmente necesita una repetición no codiciosa, sugiero consultar al todopoderoso ?. Esto, cuando se coloca al final de cualquier especificador de repetición de expresiones regulares, obligará a esa parte de la expresión regular a encontrar la menor cantidad de texto posible.

Dicho esto, sería muy cuidadoso con el, ?ya que, como el Destornillador sónico del Dr. Who, tiene una tendencia a hacer, ¿cómo debo decirlo, cosas "ligeramente" no deseadas si no se calibra cuidadosamente. Por ejemplo, para usar su entrada de ejemplo, identificaría ((1)(observe la falta de un segundo rparen) como una coincidencia.

Los daleks
fuente