Dividir cadena con múltiples delimitadores en Python [duplicado]

Resuelto gt565k asked hace 13 años • 5 respuestas

Encontré algunas respuestas en línea, pero no tengo experiencia con expresiones regulares, que creo que es lo que se necesita aquí.

Tengo una cadena que debe dividirse mediante un ';' o ',' Es decir, tiene que ser un punto y coma o una coma seguida de un espacio. Las comas individuales sin espacios finales no deben modificarse

Cadena de ejemplo:

"b-staged divinylsiloxane-bis-benzocyclobutene [124221-30-3], mesitylene [000108-67-8]; polymerized 1,2-dihydro-2,2,4- trimethyl quinoline [026780-96-1]"

debe dividirse en una lista que contenga lo siguiente:

('b-staged divinylsiloxane-bis-benzocyclobutene [124221-30-3]' , 'mesitylene [000108-67-8]', 'polymerized 1,2-dihydro-2,2,4- trimethyl quinoline [026780-96-1]') 
gt565k avatar Feb 15 '11 06:02 gt565k
Aceptado

Por suerte, Python tiene esto incorporado :)

import re

# Regex pattern splits on substrings "; " and ", "
re.split('; |, ', string_to_split)

Actualizar:

Siguiendo tu comentario:

>>> string_to_split = 'Beautiful, is; better*than\nugly'
>>> import re
>>> re.split('; |, |\*|\n', string_to_split)
['Beautiful', 'is', 'better', 'than', 'ugly']
Jonathan Livni avatar Feb 14 '2011 23:02 Jonathan Livni

Haz un str.replace('; ', ', ')y luego unstr.split(', ')

Joe avatar Feb 14 '2011 23:02 Joe

Aquí hay una forma segura para cualquier iterable de delimitadores, usando expresiones regulares:

>>> import re
>>> delimiters = "a", "...", "(c)"
>>> example = "stackoverflow (c) is awesome... isn't it?"
>>> regex_pattern = '|'.join(map(re.escape, delimiters))
>>> regex_pattern
'a|\\.\\.\\.|\\(c\\)'
>>> re.split(regex_pattern, example)
['st', 'ckoverflow ', ' is ', 'wesome', " isn't it?"]

re.escape permite construir el patrón automáticamente y hacer que los delimitadores escapen bien.

Aquí está esta solución como una función para su placer de copiar y pegar:

def split(delimiters, string, maxsplit=0):
    import re
    regex_pattern = '|'.join(map(re.escape, delimiters))
    return re.split(regex_pattern, string, maxsplit)

Si va a dividir con frecuencia usando los mismos delimitadores, compile su expresión regular de antemano como se describe y use RegexObject.split.


Si desea dejar los delimitadores originales en la cadena, puede cambiar la expresión regular para usar una aserción de búsqueda hacia atrás:

>>> import re
>>> delimiters = "a", "...", "(c)"
>>> example = "stackoverflow (c) is awesome... isn't it?"
>>> regex_pattern = '|'.join('(?<={})'.format(re.escape(delim)) for delim in delimiters)
>>> regex_pattern
'(?<=a)|(?<=\\.\\.\\.)|(?<=\\(c\\))'
>>> re.split(regex_pattern, example)
['sta', 'ckoverflow (c)', ' is a', 'wesome...', " isn't it?"]

(reemplace ?<=con ?=para colocar los delimitadores en el lado derecho, en lugar de en el izquierdo)

Kos avatar Nov 01 '2012 20:11 Kos

En respuesta a la respuesta anterior de Jonathan, esto sólo parece funcionar para ciertos delimitadores. Por ejemplo:

>>> a='Beautiful, is; better*than\nugly'
>>> import re
>>> re.split('; |, |\*|\n',a)
['Beautiful', 'is', 'better', 'than', 'ugly']

>>> b='1999-05-03 10:37:00'
>>> re.split('- :', b)
['1999-05-03 10:37:00']

Al poner los delimitadores entre corchetes, parece funcionar de manera más efectiva.

>>> re.split('[- :]', b)
['1999', '05', '03', '10', '37', '00']
Paul avatar Jan 09 '2013 10:01 Paul

Así es como se ve la expresión regular:

import re
# "semicolon or (a comma followed by a space)"
pattern = re.compile(r";|, ")

# "(semicolon or a comma) followed by a space"
pattern = re.compile(r"[;,] ")

print pattern.split(text)
Jochen Ritzel avatar Feb 14 '2011 23:02 Jochen Ritzel