Entfernen nicht druckbarer Zeichen aus einer Zeichenfolge in Python

Lesezeit: 6 Minuten

Entfernen nicht druckbarer Zeichen aus einer Zeichenfolge in Python
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.

Entfernen nicht druckbarer Zeichen aus einer Zeichenfolge in Python
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

Entfernen nicht druckbarer Zeichen aus einer Zeichenfolge in Python
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

1643913967 951 Entfernen nicht druckbarer Zeichen aus einer Zeichenfolge in Python
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)

Siehe Tabelle 4-9 auf Seite 175 im Zeicheneigenschaften der Unicode-Datenbank für die verfügbaren Kategorien

  • 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.

1643913967 24 Entfernen nicht druckbarer Zeichen aus einer Zeichenfolge in Python
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))}).

    – dunkler Drache

    23. Juni 2020 um 8:56 Uhr

1643913968 493 Entfernen nicht druckbarer Zeichen aus einer Zeichenfolge in Python
Alex Meyers

Noch eine weitere Option in Python 3:

re.sub(f'[^{re.escape(string.printable)}]', '', my_string)

  • 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

1643913968 863 Entfernen nicht druckbarer Zeichen aus einer Zeichenfolge in Python
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))

.

758820cookie-checkEntfernen nicht druckbarer Zeichen aus einer Zeichenfolge in Python

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy