2011-03-18 16 views
13

He estado tratando de igualar la siguiente cadena:expresiones regulares de Python: juego un paréntesis entre paréntesis

string = "TEMPLATES = (('index.html', 'home'), ('base.html', 'base'))" 

Pero por desgracia mi conocimiento de las expresiones regulares es muy limitada, como se puede ver que hay dos paréntesis que necesitan para ser emparejado, junto con el contenido dentro del segundo He intentado usar re.match("\(w*\)", string) pero no funcionó, cualquier ayuda sería muy apreciada.

Respuesta

22

Prueba esto:

import re 
w = "TEMPLATES = (('index.html', 'home'), ('base.html', 'base'))" 

# find outer parens 
outer = re.compile("\((.+)\)") 
m = outer.search(w) 
inner_str = m.group(1) 

# find inner pairs 
innerre = re.compile("\('([^']+)', '([^']+)'\)") 

results = innerre.findall(inner_str) 
for x,y in results: 
    print("%s <-> %s" % (x,y)) 

de salida:

index.html <-> home 
base.html <-> base 

Explicación:

outer coincide con el primer grupo de partida paréntesis utilizando \( y \); de forma predeterminada, search encuentra la coincidencia más larga, lo que nos da el par más externo (). La coincidencia m contiene exactamente lo que hay entre esos paréntesis externos; su contenido corresponde al .+ bit de outer.

innerre partidos exactamente uno de sus pares ('a', 'b'), utilizando de nuevo \( y \) para que coincida con los parens contenido en su cadena de entrada, y utilizando dos grupos dentro del ' ' para que coincida con las cuerdas dentro de las comillas simples.

A continuación, utilizamos findall (en lugar de search o match) para obtener todos los partidos para innerre (en lugar de sólo uno). En este punto, results es una lista de pares, como lo demuestra el ciclo de impresión.

Actualización: para que coincida con todo el asunto, podría intentar algo como esto:

rx = re.compile("^TEMPLATES = \(.+\)") 
rx.match(w) 
+0

gracias por la respuesta, pero ¿es posible hacer coincidir toda la cadena incluyendo la parte "TEMPLATES =" para que pueda reemplazar todo con otra cadena ? – Paulo

+0

@paulo: He agregado una expresión regular que coincide con toda la cadena. – phooji

+0

muchas gracias, realmente agradezco su ayuda, y gracias a todos los que contribuyeron: D – Paulo

1

Su muestra está buscando paren abierto seguido de cero o más letra w seguido de cierre paren. Probablemente quiera usar \ w en lugar de w, pero eso no funcionará en su caso de todos modos, porque tiene caracteres que no son palabras al lado de la paren abierta.

Creo que debería considerar dividir la cadena en las comas en su lugar. ¿Cuál es tu objetivo final?

-2

Utilice mejor el módulo de análisis adecuado, como pyparsing aquí.

6

En primer lugar, usar \( no es suficiente para que coincida con un paréntesis. Python normalmente reacciona a algunas secuencias de escape en sus cadenas, por lo que interpreta \( como simple (. Debería escribir \\( o usar una cadena sin formato, p. Ej. r'\(' o r"\(".

En segundo lugar, cuando usa re.match, está anclando la búsqueda de expresiones regulares al inicio de la cadena. Si desea buscar el patrón en cualquier lugar de la cadena, use re.search.

Al igual que Joseph dijo en su respuesta, no está exactamente claro qué es lo que quiere encontrar. Por ejemplo:

string = "TEMPLATES = (('index.html', 'home'), ('base.html', 'base'))" 
print re.findall(r'\([^()]*\)', string) 

will print

["('index.html', 'home')", "('base.html', 'base')"] 

EDIT:

mi error, @phooji is right: Escapar es irrelevante en este caso específico. Pero re.match contra re.search o re.findall sigue siendo importante.

+0

lo que quiere hacer es coincidir con la cadena "PLANTILLAS = (('index.html', 'home'), ('base.html', 'base'))" y reemplazarlo con otra cadena, ¿hay alguna manera de que coincida con el "TEMPLATES =" ¿parte junto con el paréntesis? Por cierto gracias por la explicación – Paulo

+0

En realidad 're.match (" \ (hello \) "," (hello) ")' funciona bien, aunque estoy de acuerdo en que generalmente es más fácil usar siempre 'r" ... "' para los literales de expresiones regulares. – phooji

+0

@paulo: ¿Qué intentas hacer con esa coincidencia, verificar el formato? –

2

Si sus cadenas parecen código Python válido de todos modos se puede hacer esto:

import ast 
var, s = [part.strip() for part in 
    "TEMPLATES = (('index.html', 'home'), ('base.html', 'base'))".split('=')] 
result= ast.literal_eval(s) 
Cuestiones relacionadas