expresiones regulares para obtener todo el texto fuera de los corchetes

Estoy tratando de agarrar cualquier texto fuera de los corchetes con una expresión regular.

Cadena de ejemplo

Josie Smith [3996 COLLEGE AVENUE, SOMETOWN, MD 21003] Mugsy Dog Smith [2560 OAK ST, GLENMEADE, WI 14098]

Soy capaz de obtener el texto dentro de los corchetes con éxito con:

addrs = re.findall(r"\[(.*?)\]", example_str) print addrs [u'3996 COLLEGE AVENUE, SOMETOWN, MD 21003',u'2560 OAK ST, GLENMEADE, WI 14098'] 

pero estoy teniendo problemas para conseguir algo fuera de los corchetes. He intentado algo como lo siguiente:

 names = re.findall(r"(.*?)\[.*\]+", example_str) 

pero que solo encuentra el primer nombre:

 print names [u'Josie Smith '] 

Hasta ahora solo he visto una cadena que contiene uno o dos combos de name [address] , pero supongo que podría haber cualquier número de ellos en una cadena.

Si no hay corchetes nesteds, puedes hacer esto:

 re.findall(r'(.*?)\[.*?\]', example_str) 

Sin embargo, ni siquiera necesitas una expresión regular aquí. Solo dividir entre paréntesis:

 (s.split(']')[-1] for s in example_str.split('[')) 

La única razón por la que su bash no funcionó:

 re.findall(r"(.*?)\[.*\]+", example_str) 

… es que estabas haciendo una partida no codiciosa entre paréntesis, lo que significa que estaba capturando todo, desde el primer paréntesis abierto hasta el último paréntesis de cierre, en lugar de capturar solo el primer par de paréntesis.


Además, el + en el final parece equivocado. Si tuviera 'abc [def][ghi] jkl[mno]' , ¿desearía recuperar ['abc ', '', ' jkl'] o ['abc ', ' jkl'] ? Si el primero, no agregue el + . Si es lo último, hazlo, pero luego debes colocar todo el patrón entre corchetes en un grupo que no captura: r'(.*?)(?:\[.*?\])+ .


Si puede haber texto adicional después del último corchete, el método de split funcionará bien, o podría usar re.split lugar de re.findall … pero si desea ajustar su expresión regular original para trabajar con eso, puede hacerlo.

En inglés, lo que desea es cualquier subcadena (no codiciosa) antes de una subcadena entre corchetes o el final de la cadena, ¿verdad?

Por lo tanto, necesitas una alternancia entre \[.*?\] Y $ . Por supuesto, necesita agrupar eso para escribir la alternancia, y no quiere capturar el grupo. Asi que:

 re.findall(r"(.*?)(?:\[.*?\]|$)", example_str) 

Si nunca hay corchetes nesteds:

 ([^[\]]+)(?:$|\[) 

Ejemplo:

 >>> import re >>> s = 'Josie Smith [3996 COLLEGE AVENUE, SOMETOWN, MD 21003]Mugsy Dog Smith [2560 OAK ST, GLENMEADE, WI 14098]' >>> re.findall(r'([^[\]]+)(?:$|\[)', s) ['Josie Smith ', 'Mugsy Dog Smith '] 

Explicación:

 ([^[\]]+) # match one or more characters that are not '[' or ']' and place in group 1 (?:$|\[) # match either a '[' or at the end of the string, do not capture 

Si desea ir con expresiones regulares y aún manejar los soportes nesteds, puede ir con:

 import re expr = re.compile("(?:^|])([^[\]]+)(?:\[|$)") print(expr.findall("myexpr[skip this[and this]]another[and skip that too]")) 

Esto producirá ['myexpr', 'another'] .

La idea es hacer coincidir cualquier cosa entre el comienzo de la cadena o a ] y el final de la cadena o un [ .

Puedes hacerlo:

  outside = re.findall(r"[^[]+(?=\[[^]]*]|$)", example_str) 

En otras palabras: todo lo que no es un corchete de apertura seguido de algo dentro de corchetes o el final de la cuerda