Supprimer des caractères non imprimables d'une chaîne de caractères en python

j'utilise pour exécuter

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

sur Perl pour se débarrasser des caractères non imprimables.

en Python il n'y a pas de classes de regex POSIX, et je ne peux pas écrire [:print:] avoir ce que je veux. Je ne connais pas de façon Python pour détecter si un caractère est imprimable ou non.

Que feriez-vous?

EDIT: Il a en charge les caractères Unicode. Chaîne.la manière imprimable les enlèvera avec plaisir de la sortie. malédiction.ASCII.isprint retournera false pour tout caractère unicode.

72
demandé sur Vinko Vrsalovic 2008-09-18 17:17:06

10 réponses

itérer sur les chaînes est malheureusement assez lent en Python. Les expressions régulières sont un ordre de grandeur plus rapide pour ce genre de chose. Tu dois juste construire la classe de personnage toi-même. Le module unicodedata est très utile pour cela, en particulier le module unicodedata.catégorie () fonction. Voir Unicode Character Database pour les descriptions des catégories.

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)
68
répondu Ants Aasma 2012-07-03 15:45:58

autant que je sache, la méthode la plus pythonique/efficace serait:

import string

filtered_string = filter(lambda x: x in string.printable, myStr)
56
répondu William Keller 2014-05-07 22:48:47

En 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})

Voir ce StackOverflow post sur la suppression de la ponctuation pour comment .translate() se compare à regex & .remplacer ()

9
répondu shawnrad 2017-05-23 12:18:23

vous pouvez essayer de configurer un filtre en utilisant la fonction unicodedata.category() :

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

voir les propriétés des caractères de la base de données Unicode pour les catégories disponibles

8
répondu Ber 2016-08-16 09:13:57

Cette fonction utilise des interprétations de la liste et la str.il fonctionne donc en temps linéaire au lieu de O (N^2):

from curses.ascii import isprint

def printable(input):
    return ''.join(char for char in input if isprint(char))
5
répondu Kirk Strauser 2012-01-14 03:52:05

Le meilleur que j'ai trouvé est maintenant (grâce à l'python-izers ci-dessus)

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

C'est le seul moyen que j'ai trouvé qui fonctionne avec des caractères Unicode / chaînes

de meilleures options?

2
répondu Vinko Vrsalovic 2008-09-18 13:47:28

celui-ci effectue plus rapidement que les autres ci-dessus. Jetez un oeil

''.join([x if x in string.printable else '' for x in Str])
1
répondu Nilav Baran Ghosh 2018-01-07 02:45:48

pour supprimer "espace blanc",

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
répondu knowingpark 2017-09-11 05:22:02

en Python il n'y a pas de classes de regex POSIX

Il y a lors de l'utilisation de la regex de la bibliothèque: https://pypi.org/project/regex/

il est bien entretenu et prend en charge Unicode regex, Posix regex et beaucoup plus. L'usage (signatures de méthode) est très similaire à re de Python .

de la documentation:

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

Les classes de caractères

POSIX sont supportées. Ils sont normalement traités comme une forme alternative de \p{...} .

(je ne suis pas affilié, juste un utilisateur.)

0
répondu Risadinha 2018-07-05 07:04:04

encore une autre option en python 3:

re.sub(f'[^{re.escape(string.printable)}]', '', my_string)
-1
répondu c6401 2018-09-27 17:22:36