colapso de espacios en blanco en una cadena

Tengo una cadena que se parece a esto:

"stuff . // : /// more-stuff .. .. ...$%$% stuff -> DD" 

y quiero quitar toda puntuación, hacer que todo esté en mayúsculas y colapsar todo el espacio en blanco para que se vea así:

 "STUFF MORE STUFF STUFF DD" 

¿Es esto posible con una expresión regular o necesito combinar más de dos? Esto es lo que tengo hasta ahora:

 def normalize(string): import re string = string.upper() rex = re.compile(r'\W') rex_s = re.compile(r'\s{2,}') result = rex.sub(' ', string) # this produces a string with tons of whitespace padding result = rex.sub('', result) # this reduces all those spaces return result 

Lo único que no funciona es el colapso de los espacios en blanco. ¿Algunas ideas?

Este es un enfoque de un solo paso (pero la mayúscula en realidad usa un método de cadena, ¡mucho más simple!):

 rex = re.compile(r'\W+') result = rex.sub(' ', strarg).upper() 

donde strarg es el argumento de la cadena ( no use nombres que incorporen sombra o módulos de biblioteca estándar, por favor ).

 s = "$$$aa1bb2 cc-dd ee_ff ggg." re.sub(r'\W+', ' ', s).upper() # ' AA1BB2 CC DD EE_FF GGG ' 

Es _ puntuacion?

 re.sub(r'[_\W]+', ' ', s).upper() # ' AA1BB2 CC DD EE FF GGG ' 

¿No quieres el espacio al principio y al final?

 re.sub(r'[_\W]+', ' ', s).strip().upper() # 'AA1BB2 CC DD EE FF GGG' 
 result = rex.sub(' ', string) # this produces a string with tons of whitespace padding result = rex.sub('', result) # this reduces all those spaces 

Porque escribiste y olvidaste usar rex_s para la segunda llamada. Además, debe sustituir al menos un espacio de nuevo o terminará con cualquier espacio de espacio múltiple que se convierta en ningún espacio, en lugar de un espacio de espacio único.

 result = rex.sub(' ', string) # this produces a string with tons of whitespace padding result = rex_s.sub(' ', result) # this reduces all those spaces 

¿Tienes que usar expresiones regulares? ¿Sientes que debes hacerlo en una línea?

 >>> import string >>> s = "stuff . // : /// more-stuff .. .. ...$%$% stuff -> DD" >>> s2 = ''.join(c for c in s if c in string.letters + ' ') >>> ' '.join(s2.split()) 'stuff morestuff stuff DD' 

funciona en python3, esto mantendrá el mismo carácter de espacio en blanco que contrajo. Por lo tanto, si tiene una pestaña y un espacio uno al lado del otro, no se colapsarán en un solo carácter.

 def collapse_whitespace_characters(raw_text): ret = '' if len(raw_text) > 1: prev_char = raw_text[0] ret += prev_char for cur_char in raw_text[1:]: if not cur_char.isspace() or cur_char != prev_char: ret += cur_char prev_char = cur_char else: ret = raw_text return ret 

éste colapsará los conjuntos de espacios en blanco en el primer carácter de espacio en blanco que ve

 def collapse_whitespace(raw_text): ret = '' if len(raw_text) > 1: prev_char = raw_text[0] ret += prev_char for cur_char in raw_text[1:]: if not cur_char.isspace() or \ (cur_char.isspace() and not prev_char.isspace()): ret += cur_char prev_char = cur_char else: ret = raw_text return ret 

>>> collapse_whitespace_characters (‘nos gustan los espacios y \ t \ t TABS AND WHATEVER \ xa0 \ xa0IS’)
‘nos gustan los espacios y \ t TABS \ tAND WHATEVER \ xa0IS’

>>> collapse_whitespace (‘nos gustan los espacios y \ t \ t TABS AND WHATEVER \ xa0 \ xa0IS’)
‘nos gustan los espacios y \ tTABS \ tAND WHATEVER \ xa0IS’

para la puntuacion

 def collapse_punctuation(raw_text): ret = '' if len(raw_text) > 1: prev_char = raw_text[0] ret += prev_char for cur_char in raw_text[1:]: if cur_char.isalnum() or cur_char != prev_char: ret += cur_char prev_char = cur_char else: ret = raw_text return ret 

para responder realmente a la pregunta

 orig = 'stuff . // : /// more-stuff .. .. ...$%$% stuff -> DD' collapse_whitespace(''.join([(c.upper() if c.isalnum() else ' ') for c in orig])) 

Como se dijo, la expresión regular sería algo así como

 re.sub('\W+', ' ', orig).upper()