Rimuovi tutti i caratteri speciali, punteggiatura e spazi dalla stringa


236

Devo rimuovere tutti i caratteri speciali, la punteggiatura e gli spazi da una stringa in modo da avere solo lettere e numeri.

Risposte:


351

Questo può essere fatto senza regex:

>>> string = "Special $#! characters   spaces 888323"
>>> ''.join(e for e in string if e.isalnum())
'Specialcharactersspaces888323'

Puoi usare str.isalnum:

S.isalnum() -> bool

Return True if all characters in S are alphanumeric
and there is at least one character in S, False otherwise.

Se insisti nell'utilizzare regex, altre soluzioni andranno bene. Tuttavia nota che se può essere fatto senza usare un'espressione regolare, questo è il modo migliore per farlo.


7
Qual è la ragione per non usare regex come regola empirica?
Chris Dutrow,

I regex di @ChrisDutrow sono più lenti delle funzioni integrate nella stringa di pitone
Diego Navarro,

Funziona solo quando la stringa è in Unicode . Altrimenti si lamenta che l'oggetto "str" ​​non ha alcun attributo "isalnum" "isnumeric" e così via.
NeoJi,

10
@DiegoNavarro tranne che non è vero, ho confrontato entrambe le isalnum()versioni regex e, e quella regex è più veloce del 50-75%
Francisco Couzo il

2
Inoltre: "Per le stringhe a 8 bit, questo metodo dipende dalle impostazioni locali."! Quindi l'alternativa regex è strettamente migliore!
Antti Haapala,

232

Ecco una regex per abbinare una stringa di caratteri che non sono lettere o numeri:

[^A-Za-z0-9]+

Ecco il comando Python per effettuare una sostituzione regex:

re.sub('[^A-Za-z0-9]+', '', mystring)

10
KISS: Keep It Simple Stupid! Questo è più breve e molto più facile da leggere rispetto alle soluzioni non regex e può anche essere più veloce. (Tuttavia, aggiungerei un +quantificatore per migliorare un po 'la sua efficienza.)
ridgerunner

1
questo rimuove anche gli spazi tra le parole, "great place" -> "greatplace". Come evitarlo?
Reihan_amn

5
@Reihan_amn Basta aggiungere uno spazio alla regex, in modo che diventi:[^A-Za-z0-9 ]+
ostroon

1
@ andy-white puoi per favore aggiungere lo spazio alla regex nella risposta? Lo spazio non è un personaggio speciale ...
Ufo

3
Immagino che questo non funzioni con il carattere modificato in altre lingue, come á , ö , ñ , ecc. Ho ragione? Se è così, come sarebbe la regex per questo?
HuLu ViCa,

50

Modo più breve:

import re
cleanString = re.sub('\W+','', string )

Se vuoi spazi tra parole e numeri sostituisci '' con ''


3
Tranne che _ è in \ w ed è un carattere speciale nel contesto di questa domanda.
kkurian,

Dipende dal contesto: il carattere di sottolineatura è molto utile per i nomi di file e altri identificatori, al punto che non lo considero un carattere speciale ma piuttosto uno spazio igienizzato. In genere uso questo metodo da solo.
Echelon,

1
r'\W+'- leggermente fuori tema (e molto pedante) ma suggerisco l'abitudine che tutti gli schemi regex siano stringhe grezze
Bob Stein

2
Questa procedura non considera il trattino basso (_) come un carattere speciale.
Md. Sabbir Ahmed,

30

Dopo aver visto questo, ero interessato ad espandere le risposte fornite scoprendo quali vengono eseguite nel minor tempo possibile, quindi ho esaminato alcune delle risposte proposte con timeitdue delle stringhe di esempio:

  • string1 = 'Special $#! characters spaces 888323'
  • string2 = 'how much for the maple syrup? $20.99? That s ricidulous!!!'

Esempio 1

'.join(e for e in string if e.isalnum())

  • string1 - Risultato: 10.7061979771
  • string2 - Risultato: 7.78372597694

Esempio 2

import re re.sub('[^A-Za-z0-9]+', '', string)

  • string1 - Risultato: 7.10785102844
  • string2 - Risultato: 4.12814903259

Esempio 3

import re re.sub('\W+','', string)

  • string1 - Risultato: 3.11899876595
  • string2 - Risultato: 2.78014397621

I risultati sopra riportati sono un prodotto del risultato più basso restituito da una media di: repeat(3, 2000000)

L'esempio 3 può essere 3 volte più veloce dell'esempio 1 .


@kkurian Se leggi l'inizio della mia risposta, questo è semplicemente un confronto tra le soluzioni precedentemente proposte sopra. Si potrebbe desiderare di commento sulla risposta di origine ... stackoverflow.com/a/25183802/2560922
mbeacom

Oh, vedo dove stai andando con questo. Fatto!
kkurian,

1
Devi considerare l'Esempio 3, quando hai a che fare con un corpus di grandi dimensioni.
HARSH NILESH PATHAK,

Valido! Grazie per averlo notato.
mbeacom,

puoi confrontare la mia risposta''.join([*filter(str.isalnum, string)])
Grijesh Chauhan,

22

Python 2. *

Penso che filter(str.isalnum, string)funzioni

In [20]: filter(str.isalnum, 'string with special chars like !,#$% etcs.')
Out[20]: 'stringwithspecialcharslikeetcs'

Python 3. *

In Python3, la filter( )funzione restituisce un oggetto iterabile (invece di stringa diversamente da sopra). Bisogna ricollegarsi per ottenere una stringa da itertable:

''.join(filter(str.isalnum, string)) 

o per passare listin join usare ( non sono sicuro ma può essere veloce un po ' )

''.join([*filter(str.isalnum, string)])

nota: decompressione [*args]valida in Python> = 3.5


4
@Alexey correggere, In python3 map, filtere reduce restituisce oggetti itertable invece. Sempre in Python3 + preferirò ''.join(filter(str.isalnum, string)) (o passare la lista nell'uso del join ''.join([*filter(str.isalnum, string)])) rispetto alla risposta accettata.
Grijesh Chauhan

Non ne sono certo ''.join(filter(str.isalnum, string)) sia un miglioramento filter(str.isalnum, string), almeno da leggere. È davvero questo il modo Pythreenic (sì, puoi usarlo) per farlo?
TheProletariat il

1
@TheProletariat Il punto è semplicementefilter(str.isalnum, string) non restituire la stringa in Python3 come filter( )in Python-3 restituisce iteratore anziché tipo di argomento a differenza di Python-2. +
Grijesh Chauhan

@GrijeshChauhan, penso che dovresti aggiornare la tua risposta per includere sia i tuoi consigli Python2 che Python3.
mwfearnley

18
#!/usr/bin/python
import re

strs = "how much for the maple syrup? $20.99? That's ricidulous!!!"
print strs
nstr = re.sub(r'[?|$|.|!]',r'',strs)
print nstr
nestr = re.sub(r'[^a-zA-Z0-9 ]',r'',nstr)
print nestr

puoi aggiungere un carattere più speciale e questo verrà sostituito da "" significa che nulla verrà rimosso.


16

Diversamente da chiunque altro abbia usato regex, proverei ad escludere ogni personaggio che non lo è quello che voglio, invece di elencare esplicitamente ciò che non voglio.

Ad esempio, se desidero solo caratteri dalla "a alla z" (lettere maiuscole e minuscole) e numeri, escluderei tutto il resto:

import re
s = re.sub(r"[^a-zA-Z0-9]","",s)

Questo significa "sostituisci ogni carattere che non sia un numero o un carattere nell'intervallo" dalla a alla z "o" dalla A alla Z "con una stringa vuota".

In effetti, se inserisci il carattere speciale ^nel primo posto della tua regex, otterrai la negazione.

Suggerimento extra: se devi anche minuscolare il risultato, puoi rendere il regex ancora più veloce e più facile, a patto che non trovi mai lettere maiuscole.

import re
s = re.sub(r"[^a-z0-9]","",s.lower())

9

Supponendo che tu voglia usare un regex e desideri / hai bisogno del codice 2.x Unicode-cognizant che è pronto per 2to3:

>>> import re
>>> rx = re.compile(u'[\W_]+', re.UNICODE)
>>> data = u''.join(unichr(i) for i in range(256))
>>> rx.sub(u'', data)
u'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\xaa\xb2 [snip] \xfe\xff'
>>>

7
s = re.sub(r"[-()\"#/@;:<>{}`+=~|.!?,]", "", s)

6

L'approccio più generico sta usando le 'categorie' della tabella unicodedata che classifica ogni singolo carattere. Ad esempio, il codice seguente filtra solo i caratteri stampabili in base alla loro categoria:

import unicodedata
# strip of crap characters (based on the Unicode database
# categorization:
# http://www.sql-und-xml.de/unicode-database/#kategorien

PRINTABLE = set(('Lu', 'Ll', 'Nd', 'Zs'))

def filter_non_printable(s):
    result = []
    ws_last = False
    for c in s:
        c = unicodedata.category(c) in PRINTABLE and c or u'#'
        result.append(c)
    return u''.join(result).replace(u'#', u' ')

Guarda l'URL indicato sopra per tutte le categorie correlate. Ovviamente puoi anche filtrare in base alle categorie di punteggiatura.


Cosa c'è $alla fine di ogni riga?
John Machin,

Se è un problema di copia e incolla, dovresti risolverlo allora?
Olli

5

string.punctuation contiene i seguenti caratteri:

'"# $% & \! '() * +, - / :; <=> @ [\] ^ _`.? {|} ~'

Puoi usare le funzioni translate e Maketrans per mappare punteggiatura a valori vuoti (sostituisci)

import string

'This, is. A test!'.translate(str.maketrans('', '', string.punctuation))

Produzione:

'This is A test'

4

Usa tradurre:

import string

def clean(instr):
    return instr.translate(None, string.punctuation + ' ')

Avvertenza: funziona solo su stringhe ASCII.


Differenza di versione? Ottengo TypeError: translate() takes exactly one argument (2 given)con py3.4
matt wilkie il

1
import re
my_string = """Strings are amongst the most popular data types in Python. We can create the strings by enclosing characters in quotes. Python treats single quotes the 

come le doppie virgolette. "" "

# if we need to count the word python that ends with or without ',' or '.' at end

count = 0
for i in text:
    if i.endswith("."):
        text[count] = re.sub("^([a-z]+)(.)?$", r"\1", i)
    count += 1
print("The count of Python : ", text.count("python"))

0
import re
abc = "askhnl#$%askdjalsdk"
ddd = abc.replace("#$%","")
print (ddd)

e vedrai il tuo risultato come

'askhnlaskdjalsdk


4
aspetta .... hai importato rema non l' hai mai usato. I tuoi replacecriteri funzionano solo per questa stringa specifica. E se la tua stringa fosse abc = "askhnl#$%!askdjalsdk"? Non credo funzionerà su qualcosa di diverso dal #$%modello. Potrebbe voler modificarlo
JChao,

0

Rimozione di punteggiatura, numeri e caratteri speciali

Esempio :-

inserisci qui la descrizione dell'immagine

Codice

combi['tidy_tweet'] = combi['tidy_tweet'].str.replace("[^a-zA-Z#]", " ") 

Risultato:- inserisci qui la descrizione dell'immagine

Grazie :)


0

Per le altre lingue come il tedesco, spagnolo, danese, francese, ecc che contengono caratteri speciali (come il tedesco "Umlaute", come ü, ä,ö ) è sufficiente aggiungere questi per la stringa di ricerca regex:

Esempio per il tedesco:

re.sub('[^A-ZÜÖÄa-z0-9]+', '', mystring)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.