it-swarm-eu.dev

Odizolování netisknutelných znaků z řetězce v pythonu

Používám ke spuštění

$s =~ s/[^[:print:]]//g;

na Perlu se zbavit nepotisknutelných znaků. 

V Pythonu neexistují žádné POSX regex třídy a nemohu psát [: print:], což znamená, co chci. Vím, že v Pythonu není žádný způsob, jak zjistit, zda je znak tisknutelný nebo ne. 

Co bys dělal? 

EDIT: Musí podporovat také znaky Unicode. Řetězce.printable způsob, jak je šťastně strip je z výstupu. curses.ascii.isprint vrátí false pro každý znak Unicode.

75
Vinko Vrsalovic

Iterace nad řetězci je v Pythonu bohužel spíše pomalá. Regulární výrazy jsou pro tento druh věcí mnohem rychlejší. Stačí si postavit třídu postav sami. Modul unicodedata je pro to velmi užitečný, zejména funkce unicodedata.category (). Viz Unicode Character Database pro popis kategorií.

import unicodedata, re

all_chars = (unichr(i) for i in xrange(0x110000))
control_chars = ''.join(c for c in all_chars if unicodedata.category(c) == 'Cc')
# or equivalently and much more efficiently
control_chars = ''.join(map(unichr, range(0,32) + range(127,160)))

control_char_re = re.compile('[%s]' % re.escape(control_chars))

def remove_control_chars(s):
    return control_char_re.sub('', s)
70
Ants Aasma

Pokud vím, nejúčinnější metodou Pythonic by bylo:

import string

filtered_string = filter(lambda x: x in string.printable, myStr)
60
William Keller

V jazyce Python 3

def filter_nonprintable(text):
    import string
    # Get the difference of all ASCII characters from the set of printable characters
    nonprintable = set([chr(i) for i in range(128)]).difference(string.printable)
    # Use translate to remove all non-printable characters
    return text.translate({ord(character):None for character in nonprintable})

Viz tento příspěvek StackOverflow při odstraňování interpunkce pro to, jak se .translate () porovnává s regex & .replace ()

9
shawnrad

Můžete zkusit nastavit filtr pomocí funkce unicodedata.category():

printable = Set('Lu', 'Ll', ...)
def filter_non_printable(str):
  return ''.join(c for c in str if unicodedata.category(c) in printable)

Viz vlastnosti znaku databáze Unicode pro dostupné kategorie

8
Ber

Tato funkce používá seznamová porozumění a str.join, takže běží namísto O (n ^ 2) v lineárním čase:

from curses.ascii import isprint

def printable(input):
    return ''.join(char for char in input if isprint(char))
5
Kirk Strauser

To nejlepší, s čím jsem teď přišel, je (díky python-izonantům výše) 

def filter_non_printable(str):
  return ''.join([c for c in str if ord(c) > 31 or ord(c) == 9])

To je jediný způsob, jak jsem zjistil, že pracuje s Unicode znaky/řetězce

Nějaké lepší možnosti?

2
Vinko Vrsalovic

V Pythonu nejsou žádné třídy POSIX regex

Používáte-li knihovnu regex: https://pypi.org/project/regex/

Je dobře udržovaný a podporuje Unicode regex, Posix regex a mnoho dalších. Použití (signatury metod) je velmi podobné Pythonova re.

Z dokumentace:

[[:alpha:]]; [[:^alpha:]]

Podporovány jsou znakové třídy POSIX. Tyto Jsou obvykle považovány za alternativní formu \p{...}.

(Nejsem přidružený, jen uživatel.)

1
Risadinha

Jedna z níže uvedených operací probíhá rychleji než ostatní výše. Podívej se

''.join([x if x in string.printable else '' for x in Str])
1

Chcete-li odstranit mezery,

import re
t = """
\n\t<p>&nbsp;</p>\n\t<p>&nbsp;</p>\n\t<p>&nbsp;</p>\n\t<p>&nbsp;</p>\n\t<p>
"""
pat = re.compile(r'[\t\n]')
print(pat.sub("", t))
0
knowingpark

Následující bude pracovat s Unicode vstup a je poměrně rychlý ...

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('\x00\x11Hello') == 'Hello'
assert make_printable('') == ''

Moje vlastní testování naznačuje, že tento přístup je rychlejší než funkce, které iterují přes řetězec a vrací výsledek pomocí str.join.

0
ChrisP