web-dev-qa-db-fra.com

Supprimer des caractères de contrôle d'une chaîne en python

J'ai actuellement le code suivant

def removeControlCharacters(line):
    i = 0
    for c in line:
        if (c < chr(32)):
            line = line[:i - 1] + line[i+1:]
            i += 1
    return line

Cela ne fonctionne tout simplement pas s'il y a plus d'un caractère à supprimer.

36
David

Il y a centaines de caractères de contrôle en unicode. Si vous désinfectez des données provenant du Web ou de toute autre source susceptible de contenir des caractères non ASCII, vous aurez besoin du module unicodedata de Python. La fonction unicodedata.category(…) renvoie le code de catégorie unicode (par exemple, caractère de contrôle, espace, lettre, etc.) de n’importe quel caractère. Pour les caractères de contrôle, la catégorie commence toujours par "C".

Cet extrait supprime tous les caractères de contrôle d'une chaîne.

import unicodedata
def remove_control_characters(s):
    return "".join(ch for ch in s if unicodedata.category(ch)[0]!="C")

Exemples de catégories unicode }:

>>> from unicodedata import category
>>> category('\r')      # carriage return --> Cc : control character
'Cc'
>>> category('\0')      # null character ---> Cc : control character
'Cc'
>>> category('\t')      # tab --------------> Cc : control character
'Cc'
>>> category(' ')       # space ------------> Zs : separator, space
'Zs'
>>> category(u'\u200A') # hair space -------> Zs : separator, space
'Zs'
>>> category(u'\u200b') # zero width space -> Cf : control character, formatting
'Cf'
>>> category('A')       # letter "A" -------> Lu : letter, uppercase
'Lu'
>>> category(u'\u4e21') # 両 ---------------> Lo : letter, other
'Lo'
>>> category(',')       # comma  -----------> Po : punctuation
'Po'
>>>
98
Alex Quinn

Vous pouvez utiliser str.translate avec la carte appropriée, par exemple comme ceci:

>>> mpa = dict.fromkeys(range(32))
>>> 'abc\02de'.translate(mpa)
'abcde'
24
SilentGhost

Toute personne intéressée par une classe de caractères regex qui correspond à n’importe quel caractère Unicode control character peut utiliser [\x00-\x1f\x7f-\x9f].

Vous pouvez le tester comme ceci:

>>> import unicodedata, re, sys
>>> all_chars = [chr(i) for i in range(sys.maxunicode)]
>>> control_chars = ''.join(c for c in all_chars if unicodedata.category(c) == 'Cc')
>>> expanded_class = ''.join(c for c in all_chars if re.match(r'[\x00-\x1f\x7f-\x9f]', c))
>>> control_chars == expanded_class
True

Donc, pour supprimer les caractères de contrôle en utilisant re, utilisez ce qui suit:

>>> re.sub(r'[\x00-\x1f\x7f-\x9f]', '', 'abc\02de')
'abcde'
8
AXO

Votre implémentation est incorrecte car la valeur de i est incorrecte. Cependant, ce n’est pas le seul problème: il utilise également de manière répétée des opérations de chaîne lente, ce qui signifie qu’il s’exécute dans O (n2) au lieu de O (n). Essayez ceci à la place:

return ''.join(c for c in line if ord(c) >= 32)
7
Mark Byers

Et pour Python 2, avec la variable translate intégrée:

import string
all_bytes = string.maketrans('', '')  # String of 256 characters with (byte) value 0 to 255

line.translate(all_bytes, all_bytes[:32])  # All bytes < 32 are deleted (the second argument lists the bytes to delete)
6
Eric O Lebigot
filter(string.printable[:-5].__contains__,line)
2
Kabie

Vous modifiez la ligne lors de son itération. Quelque chose comme ''.join([x for x in line if ord(x) >= 32])

2
khachik

C’est la méthode la plus simple, la plus complète et la plus robuste que je connaisse. Cela nécessite toutefois une dépendance externe. Je considère que cela vaut la peine pour la plupart des projets.

pip install regex

import regex as re
def remove_control_characters(str):
    return re.sub(r'\p{C}', '', 'my-string')

\p{C} est la propriété de caractère unicode pour les caractères de contrôle. Vous pouvez donc laisser au consortium unicode les noms de millions de caractères unicode disponibles qui doivent être considérés comme des contrôles. Il existe également d’autres propriétés de caractère extrêmement utiles que j’utilise fréquemment, par exemple \p{Z} pour tout type d’espace.

1
cmc