Entfernen Sie alle Sonderzeichen, Satzzeichen und Leerzeichen aus der Zeichenfolge

236

Ich muss alle Sonderzeichen, Satzzeichen und Leerzeichen aus einer Zeichenfolge entfernen, damit ich nur Buchstaben und Zahlen habe.

user664546
quelle

Antworten:

351

Dies kann ohne Regex erfolgen:

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

Sie können verwenden 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.

Wenn Sie auf der Verwendung von Regex bestehen, sind andere Lösungen ausreichend. Beachten Sie jedoch, dass dies der beste Weg ist, wenn dies ohne Verwendung eines regulären Ausdrucks möglich ist.

user225312
quelle
7
Was ist der Grund, warum Regex nicht als Faustregel verwendet wird?
Chris Dutrow
@ ChrisDutrow Regex sind langsamer als die in Python-Zeichenfolgen integrierten Funktionen
Diego Navarro
Dies funktioniert nur, wenn sich die Zeichenfolge im Unicode befindet . Andernfalls beschwert es sich, dass das Objekt 'str' kein Attribut 'isalnum' 'isnumeric' hat und so weiter.
NeoJi
10
@DiegoNavarro, außer das ist nicht wahr, ich habe sowohl die isalnum()als auch die Regex-Version verglichen und die Regex-Version ist 50-75% schneller
Francisco Couzo
2
Zusätzlich: "Für 8-Bit-Zeichenfolgen ist diese Methode vom Gebietsschema abhängig."! Somit ist die Regex-Alternative strikt besser!
Antti Haapala
231

Hier ist eine Regex, die einer Zeichenfolge entspricht, die keine Buchstaben oder Zahlen sind:

[^A-Za-z0-9]+

Hier ist der Python-Befehl, um eine Regex-Ersetzung durchzuführen:

re.sub('[^A-Za-z0-9]+', '', mystring)
Andy White
quelle
10
KISS: Halte es einfach dumm! Dies ist kürzer und viel einfacher zu lesen als die Nicht-Regex-Lösungen und möglicherweise auch schneller. (Allerdings würde ich einen +Quantifizierer hinzufügen , um seine Effizienz ein wenig zu verbessern.)
Ridgerunner
1
Dadurch werden auch die Leerzeichen zwischen den Wörtern "großer Ort" -> "großer Ort" entfernt. Wie vermeide ich das?
Reihan_amn
5
@Reihan_amn Fügen Sie einfach ein Leerzeichen zur Regex hinzu, so wird es:[^A-Za-z0-9 ]+
Ostroon
1
@ andy-white kannst du bitte das Leerzeichen in der Antwort zum regulären Ausdruck hinzufügen? Der Weltraum ist kein Sonderzeichen ...
Ufos
3
Ich denke, das funktioniert nicht mit modifizierten Zeichen in anderen Sprachen wie á , ö , ñ usw. Habe ich recht? Wenn ja, wie wäre es der reguläre Ausdruck dafür?
HuLu ViCa
49

Kürzere Art:

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

Wenn Sie Leerzeichen zwischen Wörtern und Zahlen wünschen, ersetzen Sie '' durch ''

tuxErrante
quelle
3
Nur dass _ in \ w ist und im Kontext dieser Frage ein Sonderzeichen ist.
kkurian
Abhängig vom Kontext - Unterstrich ist sehr nützlich für Dateinamen und andere Bezeichner, bis zu dem Punkt, dass ich ihn nicht als Sonderzeichen, sondern als bereinigten Raum behandle. Ich verwende diese Methode im Allgemeinen selbst.
Echelon
1
r'\W+'- etwas vom Thema abweichen (und sehr pedantisch), aber ich schlage vor, dass alle Regex-Muster rohe Zeichenfolgen sind
Bob Stein
2
Bei dieser Prozedur wird der Unterstrich (_) nicht als Sonderzeichen behandelt.
Md. Sabbir Ahmed
30

Nachdem ich dies gesehen hatte, war ich daran interessiert, die bereitgestellten Antworten zu erweitern, indem ich herausfand, welche in kürzester Zeit ausgeführt werden. Daher ging ich einige der vorgeschlagenen Antworten durch und verglich sie mit timeitzwei der Beispielzeichenfolgen:

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

Beispiel 1

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

  • string1 - Ergebnis: 10.7061979771
  • string2 - Ergebnis: 7.78372597694

Beispiel 2

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

  • string1 - Ergebnis: 7.10785102844
  • string2 - Ergebnis: 4.12814903259

Beispiel 3

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

  • string1 - Ergebnis: 3.11899876595
  • string2 - Ergebnis: 2.78014397621

Die obigen Ergebnisse sind ein Produkt des niedrigsten zurückgegebenen Ergebnisses aus einem Durchschnitt von: repeat(3, 2000000)

Beispiel 3 kann 3x schneller sein als Beispiel 1 .

mbeacom
quelle
@kkurian Wenn Sie den Anfang meiner Antwort lesen, ist dies lediglich ein Vergleich der oben vorgeschlagenen Lösungen. Vielleicht möchten Sie die ursprüngliche Antwort kommentieren ... stackoverflow.com/a/25183802/2560922
mbeacom
Oh, ich sehe, wohin du damit gehst. Getan!
kkurian
1
Muss Beispiel 3 berücksichtigen, wenn es sich um einen großen Korpus handelt.
HARSH NILESH PATHAK
Gültig! Vielen Dank für die Notiz.
mbeacom
können Sie meine Antwort vergleichen''.join([*filter(str.isalnum, string)])
Grijesh Chauhan
22

Python 2. *

Ich denke filter(str.isalnum, string)funktioniert einfach

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

Python 3. *

In Python3 filter( )würde die Funktion ein itertable-Objekt zurückgeben (anstelle einer Zeichenfolge wie oben). Man muss sich wieder verbinden, um eine Zeichenfolge aus itertable zu erhalten:

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

oder listJoin-Verwendung zu übergeben ( nicht sicher, kann aber ein bisschen schnell sein )

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

Hinweis: Auspacken [*args]gültig von Python> = 3.5

Grijesh Chauhan
quelle
4
@Alexey korrigieren, In python3 map, filterund reduce kehrt itertable Objekt statt. Noch in Python3 + werde ich die akzeptierte Antwort vorziehen ''.join(filter(str.isalnum, string)) (oder die Liste im Join-Gebrauch übergeben ''.join([*filter(str.isalnum, string)])).
Grijesh Chauhan
Ich bin mir nicht sicher, ob ''.join(filter(str.isalnum, string))es eine Verbesserung ist filter(str.isalnum, string), zumindest zu lesen. Ist das wirklich die pythreenische (ja, das können Sie verwenden) Methode, um dies zu tun?
TheProletariat
1
@TheProletariat Der Punkt ist einfachfilter(str.isalnum, string) nicht zurück Zeichenfolge in Python3 wie filter( )in Python3 Iterator zurückgibt , anstatt Argumenttyp im Gegensatz zu Python-2 +.
Grijesh Chauhan
@GrijeshChauhan, ich denke, Sie sollten Ihre Antwort aktualisieren, um sowohl Ihre Python2- als auch Ihre Python3-Empfehlungen aufzunehmen.
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

Sie können weitere Sonderzeichen hinzufügen, die durch '' ersetzt werden. Dies bedeutet nichts, dh sie werden entfernt.

pkm
quelle
16

Anders als alle anderen, die Regex verwenden, würde ich versuchen, jedes Zeichen auszuschließen, das nicht das ist, was ich will, anstatt explizit aufzuzählen, was ich nicht will.

Wenn ich zum Beispiel nur Zeichen von 'a bis z' (Groß- und Kleinbuchstaben) und Zahlen möchte, würde ich alles andere ausschließen:

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

Dies bedeutet "Ersetzen Sie jedes Zeichen, das keine Zahl ist, oder ein Zeichen im Bereich 'a bis z' oder 'A bis Z' durch eine leere Zeichenfolge".

Wenn Sie das Sonderzeichen ^an der ersten Stelle Ihrer Regex einfügen , erhalten Sie die Negation.

Zusätzlicher Tipp: Wenn Sie das Ergebnis auch in Kleinbuchstaben schreiben müssen , können Sie den regulären Ausdruck noch schneller und einfacher machen, solange Sie jetzt keine Großbuchstaben finden.

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

Angenommen, Sie möchten einen regulären Ausdruck verwenden und möchten / benötigen einen Unicode-erkennenden 2.x-Code, der 2to3-fähig ist:

>>> 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'
>>>
John Machin
quelle
7
s = re.sub(r"[-()\"#/@;:<>{}`+=~|.!?,]", "", s)
sneha
quelle
6

Der allgemeinste Ansatz ist die Verwendung der 'Kategorien' der Unicodedata-Tabelle, die jedes einzelne Zeichen klassifiziert. Der folgende Code filtert beispielsweise nur druckbare Zeichen basierend auf ihrer Kategorie:

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' ')

Schauen Sie sich die oben angegebene URL für alle verwandten Kategorien an. Sie können natürlich auch nach den Interpunktionskategorien filtern.

Andreas Jung
quelle
Was ist mit dem $am Ende jeder Zeile?
John Machin
Wenn es sich um ein Copy & Paste-Problem handelt, sollten Sie es dann beheben?
Olli
5

string.punctuation enthält folgende Zeichen:

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

Sie können die Funktionen translate und maketrans verwenden, um Interpunktionen leeren Werten zuzuordnen (ersetzen).

import string

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

Ausgabe:

'This is A test'
Vlad Bezden
quelle
4

Einen Übersetzer benutzen:

import string

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

Vorsichtsmaßnahme: Funktioniert nur bei ASCII-Saiten.

jjmurre
quelle
Versionsunterschied? Ich bekomme TypeError: translate() takes exactly one argument (2 given)mit py3.4
matt wilkie
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 

das gleiche wie doppelte Anführungszeichen. "" "

# 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"))
Vinay Kumar Kuresi
quelle
0
import re
abc = "askhnl#$%askdjalsdk"
ddd = abc.replace("#$%","")
print (ddd)

und du wirst dein Ergebnis sehen als

'askhnlaskdjalsdk

Dsw Wds
quelle
4
Warten Sie ... Sie haben es importiert, reaber nie verwendet. Ihre replaceKriterien funktionieren nur für diese bestimmte Zeichenfolge. Was ist, wenn Ihre Zeichenfolge ist abc = "askhnl#$%!askdjalsdk"? Ich denke nicht, dass etwas anderes als das #$%Muster funktionieren wird.
Könnte
0

Interpunktionen, Zahlen und Sonderzeichen entfernen

Beispiel: -

Geben Sie hier die Bildbeschreibung ein

Code

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

Ergebnis:- Geben Sie hier die Bildbeschreibung ein

Vielen Dank :)

Harish Kumawat
quelle