130 votes

Comment puis-je supprimer les caractères non ASCII tout en laissant les points et les espaces ?

Je travaille avec un fichier .txt. Je veux une chaîne de caractères contenant le texte du fichier, sans caractères non ASCII. Cependant, je veux laisser les espaces et les points. Pour l'instant, je les supprime également. Voici le code :

def onlyascii(char):
    if ord(char) < 48 or ord(char) > 127: return ''
    else: return char

def get_my_string(file_path):
    f=open(file_path,'r')
    data=f.read()
    f.close()
    filtered_data=filter(onlyascii, data)
    filtered_data = filtered_data.lower()
    return filtered_data

Comment dois-je modifier onlyascii() pour laisser les espaces et les points ? J'imagine que ce n'est pas trop compliqué mais je n'arrive pas à comprendre.

224voto

jterrace Points 21939

Vous pouvez filtrer tous les caractères de la chaîne qui ne sont pas imprimables en utilisant string.printable comme ceci :

>>> s = "some\x00string. with\x15 funny characters"
>>> import string
>>> printable = set(string.printable)
>>> filter(lambda x: x in printable, s)
'somestring. with funny characters'

string.printable sur ma machine contient :

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c

EDIT : Sous Python 3, filter retournera un itérable. La manière correcte d'obtenir une chaîne en retour serait :

''.join(filter(lambda x: x in printable, s))

113voto

Zweedeend Points 186

Un moyen facile de passer à un codec différent est d'utiliser encode() ou decode(). Dans votre cas, vous voulez convertir en ASCII et ignorer tous les symboles qui ne sont pas supportés. Par exemple, la lettre suédoise å n'est pas un caractère ASCII :

    >>>s = u'Good bye in Swedish is Hej d\xe5'
    >>>s = s.encode('ascii',errors='ignore')
    >>>print s
    Good bye in Swedish is Hej d

Edit :

Python3 : str -> bytes -> str

>>>"Hej då".encode("ascii", errors="ignore").decode()
'hej d'

Python2 : unicode -> str -> unicode

>>> u"hej då".encode("ascii", errors="ignore").decode()
u'hej d'

Python2 : str -> unicode -> str (décodage et encodage en ordre inverse)

>>> "hej d\xe5".decode("ascii", errors="ignore").encode()
'hej d'

39voto

Noam Manos Points 145

Selon @artfulrobot, cela devrait être plus rapide que filter et lambda :

import re
re.sub(r'[^\x00-\x7f]',r'', your-non-ascii-string) 

Voir d'autres exemples ici Remplacer les caractères non ASCII par un seul espace.

8voto

Noha Elprince Points 1413

Vous pouvez utiliser le code suivant pour supprimer les lettres non anglaises :

import re
str = "123456790 ABC#%? .()"
result = re.sub(r'[^\x00-\x7f]',r'', str)
print(result)

Cela donnera

123456790 ABC#% ? .()

6voto

John Machin Points 39706

Votre question est ambiguë ; les deux premières phrases prises ensemble impliquent que vous pensez que l'espace et le "point" sont des caractères non ASCII. Ceci est incorrect. Tous les caractères tels que ord(char) <= 127 sont des caractères ASCII. Par exemple, votre fonction exclut les caractères !"#$%&\'()*+,-./ mais en inclut plusieurs autres, par exemple []{}.

Veuillez prendre du recul, réfléchir un peu et modifier votre question pour nous dire ce que vous essayez de faire, sans mentionner le mot ASCII, et pourquoi vous pensez que les caractères tels que ord(char) >= 128 sont ignorables. De plus, quelle version de Python ? Quel est l'encodage de vos données d'entrée ?

Veuillez noter que votre code lit l'ensemble du fichier d'entrée comme une seule chaîne de caractères et que votre commentaire ("excellente solution") à une autre réponse implique que vous ne vous souciez pas des nouvelles lignes dans vos données. Si votre fichier contient deux lignes comme ceci :

this is line 1
this is line 2

le résultat serait 'this is line 1this is line 2' ... est-ce que c'est ce que vous voulez vraiment ?

Une meilleure solution comprendrait :

  1. un meilleur nom pour la fonction de filtrage que onlyascii
  2. la reconnaissance du fait qu'une fonction de filtrage doit simplement retourner une valeur véridique si l'argument doit être conservé :

    def filter_func(char):
        return char == '\n' or 32 <= ord(char) <= 126
    # and later:
    filtered_data = filter(filter_func, data).lower()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X