Entfernen nicht druckbarer Zeichen aus einer Zeichenfolge in Python
Lesezeit: 6 Minuten
Vinko Vrsalović
Ich laufe
$s =~ s/[^[:print:]]//g;
auf Perl, um nicht druckbare Zeichen loszuwerden.
In Python gibt es keine POSIX-Regex-Klassen, und ich kann nicht schreiben [:print:] es bedeutet, was ich will. Ich kenne in Python keine Möglichkeit zu erkennen, ob ein Zeichen druckbar ist oder nicht.
Was würdest du tun?
EDIT: Es muss auch Unicode-Zeichen unterstützen. Der string.printable-Weg entfernt sie gerne aus der Ausgabe. curses.ascii.isprint gibt für jedes Unicode-Zeichen false zurück.
Ameisen Aasma
Das Iterieren über Strings ist in Python leider ziemlich langsam. Reguläre Ausdrücke sind für solche Dinge über eine Größenordnung schneller. Sie müssen nur die Charakterklasse selbst erstellen. Der Unicodedaten Modul ist dabei sehr hilfreich, besonders das unicodedata.category() Funktion. Sehen Unicode-Zeichendatenbank für Beschreibungen der Kategorien.
import unicodedata, re, itertools, sys
all_chars = (chr(i) for i in range(sys.maxunicode))
categories = {'Cc'}
control_chars="".join(c for c in all_chars if unicodedata.category(c) in categories)
# or equivalently and much more efficiently
control_chars="".join(map(chr, itertools.chain(range(0x00,0x20), range(0x7f,0xa0))))
control_char_re = re.compile('[%s]' % re.escape(control_chars))
def remove_control_chars(s):
return control_char_re.sub('', s)
Für Python2
import unicodedata, re, sys
all_chars = (unichr(i) for i in xrange(sys.maxunicode))
categories = {'Cc'}
control_chars="".join(c for c in all_chars if unicodedata.category(c) in categories)
# or equivalently and much more efficiently
control_chars="".join(map(unichr, range(0x00,0x20) + range(0x7f,0xa0)))
control_char_re = re.compile('[%s]' % re.escape(control_chars))
def remove_control_chars(s):
return control_char_re.sub('', s)
Für einige Anwendungsfälle können zusätzliche Kategorien (z. B. alle aus der Kontrolle Gruppe ist möglicherweise vorzuziehen, obwohl dies die Verarbeitungszeit verlangsamen und die Speichernutzung erheblich erhöhen kann. Anzahl Zeichen pro Kategorie:
Cc (Kontrolle): 65
Cf (Format): 161
Cs (Ersatz): 2048
Co (private Nutzung): 137468
Cn (nicht zugeordnet): 836601
Bearbeiten Hinzufügen von Vorschlägen aus den Kommentaren.
Reicht hier ‘Cc’? Ich weiß nicht, ich frage nur – mir scheint, dass einige der anderen „C“-Kategorien auch Kandidaten für diesen Filter sein könnten.
– Patrick Johnmeyer
18. September 2008 um 17:10 Uhr
Diese veröffentlichte Funktion entfernt die Hälfte der hebräischen Zeichen. Ich erhalte den gleichen Effekt für beide angegebenen Methoden.
– dotancohen
11. Dezember 12 um 15:32 Uhr
Würde string.translate() in diesem Fall aus Leistungssicht nicht schneller arbeiten? Siehe stackoverflow.com/questions/265960/…
– Kashyap
3. Oktober 13 um 20:19 Uhr
Benutzen all_chars = (unichr(i) for i in xrange(sys.maxunicode)) um den Narrow-Build-Fehler zu vermeiden.
– Danmichaelo
24. November 15 um 21:01 Uhr
Für mich control_chars == 'x00-x1fx7f-x9f' (getestet auf Python 3.5.2)
– AXO
9. September 16 um 16:03 Uhr
Wilhelm Keller
Soweit ich weiß, wäre die pythonischste/effizienteste Methode:
import string
filtered_string = filter(lambda x: x in string.printable, myStr)
Wahrscheinlich möchten Sie „filtered_string = ”.join(filter(lambda x:x in string.printable, myStr)“, damit Sie einen String zurückerhalten.
– Nathan Shively-Sanders
18. September 2008 um 13:27 Uhr
Leider enthält string.printable keine Unicode-Zeichen, und daher wird ü oder ó nicht in der Ausgabe erscheinen … vielleicht gibt es etwas anderes?
– Vinko Vrsalović ♦
18. September 2008 um 13:29 Uhr
Sie sollten ein Listenverständnis oder Generatorausdrücke verwenden, nicht Filter + Lambda. Einer davon wird zu 99,9 % schneller sein. ”.join(s für s in myStr wenn s in string.printable)
– Habnabit
18. September 08 um 22:49 Uhr
@AaronGallagher: 99,9 % schneller? Woher nehmen Sie diese Figur? Der Leistungsvergleich ist bei weitem nicht so schlecht.
– Chris Morgan
14. Januar 12 um 04:01 Uhr
Hallo Wilhelm. Diese Methode scheint alle Nicht-ASCII-Zeichen zu entfernen. Es gibt viele druckbare Nicht-ASCII-Zeichen in Unicode!
– dotancohen
11. Dezember 2012 um 15:28 Uhr
Ber
Sie könnten versuchen, einen Filter mit dem einzurichten unicodedata.category() Funktion:
import unicodedata
printable = {'Lu', 'Ll'}
def filter_non_printable(str):
return ''.join(c for c in str if unicodedata.category(c) in printable)
Sie haben ein Listenverständnis begonnen, das nicht in Ihrer letzten Zeile endete. Ich schlage vor, Sie entfernen die öffnende Klammer vollständig.
– zot
19. September 08 um 12:13 Uhr
Vielen Dank für den Hinweis. Ich habe den Beitrag entsprechend editiert
– Ber
5. Oktober 08 um 15:32 Uhr
Dies scheint die direkteste und unkomplizierteste Methode zu sein. Danke.
– dotancohen
21. Juli 13 um 5:34 Uhr
@CsabaToth Alle drei sind gültig und ergeben denselben Satz. Ihre ist vielleicht die netteste Art, ein Set-Literal anzugeben.
– Ber
4. Juni 19 um 9:56 Uhr
@AnubhavJhalani Sie können dem Filter weitere Unicode-Kategorien hinzufügen. Verwenden Sie zum Reservieren von Leerzeichen und Ziffern zusätzlich zu Buchstaben printable = {'Lu', 'Ll', Zs', 'Nd'}
– Ber
7. November 19 um 19:41 Uhr
Das Folgende funktioniert mit Unicode-Eingabe und ist ziemlich schnell …
import sys
# build a table mapping all non-printable characters to None
NOPRINT_TRANS_TABLE = {
i: None for i in range(0, sys.maxunicode + 1) if not chr(i).isprintable()
}
def make_printable(s):
"""Replace non-printable characters in a string."""
# the translate method on str removes characters
# that map to None from the string
return s.translate(NOPRINT_TRANS_TABLE)
assert make_printable('Café') == 'Café'
assert make_printable('x00x11Hello') == 'Hello'
assert make_printable('') == ''
Meine eigenen Tests deuten darauf hin, dass dieser Ansatz schneller ist als Funktionen, die die Zeichenfolge durchlaufen und ein Ergebnis mit zurückgeben str.join.
Shawnrad
In Python3,
def filter_nonprintable(text):
import itertools
# Use characters of control category
nonprintable = itertools.chain(range(0x00,0x20),range(0x7f,0xa0))
# Use translate to remove all non-printable characters
return text.translate({character:None for character in nonprintable})
In diesem StackOverflow-Beitrag zum Entfernen von Satzzeichen erfahren Sie, wie .translate() mit Regex & .replace() verglichen wird.
Die Bereiche können über generiert werden nonprintable = (ord(c) for c in (chr(i) for i in range(sys.maxunicode)) if unicodedata.category(c)=='Cc') Verwendung der Datenbankkategorien für Unicode-Zeichen wie von @Ants Aasma gezeigt.
Es wäre besser, Unicode-Bereiche zu verwenden (siehe Antwort von @Ants Aasma). Das Ergebnis wäre text.translate({c:None for c in itertools.chain(range(0x00,0x20),range(0x7f,0xa0))}).
Es wäre besser, Unicode-Bereiche zu verwenden (siehe Antwort von @Ants Aasma). Das Ergebnis wäre text.translate({c:None for c in itertools.chain(range(0x00,0x20),range(0x7f,0xa0))}).
– dunkler Drache
23. Juni 2020 um 8:56 Uhr
rmmh
Diese Funktion verwendet Listenverständnisse und str.join, sodass sie in linearer Zeit statt in O(n^2) ausgeführt wird:
from curses.ascii import isprint
def printable(input):
return ''.join(char for char in input if isprint(char))
.
7588200cookie-checkEntfernen nicht druckbarer Zeichen aus einer Zeichenfolge in Pythonyes