web-dev-qa-db-fra.com

Comment puis-je supprimer des caractères non-ASCII tout en laissant des points et des espaces à l'aide de Python?

Je travaille avec un fichier .txt. Je veux une chaîne du texte du fichier sans caractères non-ASCII. Cependant, je veux laisser des espaces et des points. À l'heure actuelle, je les dépouille aussi. 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 des espaces et des points? J'imagine que ce n'est pas trop compliqué mais je n'arrive pas à comprendre.

76
user1120342

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
148
jterrace

Un moyen simple de passer à un autre codec consiste à utiliser encode () ou decode (). Dans votre cas, vous souhaitez convertir en ASCII et ignorer tous les symboles qui ne sont pas pris en charge. 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

Modifier:

Python3: str -> octets -> 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écoder et encoder dans l'ordre inverse)

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

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

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

Voir d'autres exemples ici http://stackoverflow.com/questions/20078816/replace-non-ascii-characters-with-a-single-space/20079244#20079244

19
Noam Manos

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

Revenez en arrière, réfléchissez un peu et modifiez votre question pour nous indiquer 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. Aussi: quelle version de Python? Quel est l'encodage de vos données d'entrée?

Veuillez noter que votre code lit l'intégralité du fichier d'entrée sous forme de chaîne unique et que votre commentaire ("excellente solution") à une autre réponse implique que vous ne vous souciez pas des retours à la ligne 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 ce que vous voulez vraiment?

Une solution plus large comprendrait:

  1. un meilleur nom pour la fonction de filtrage que onlyascii 
  2. reconnaissance du fait qu'une fonction de filtrage doit simplement renvoyer une valeur de vérité pour conserver l'argument:

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

Si vous voulez des caractères ascii imprimables, vous devriez probablement corriger votre code pour:

if ord(char) < 32 or ord(char) > 126: return ''

c'est l'équivalent de string.printable (réponse de @jterrace), à ​​l'exception de l'absence de retour et d'onglets ('\ t', '\ n', '\ x0b', '\ x0c' et '\ r') mais ne correspond pas à la gamme sur votre question

1
joaquin

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 va retourner

123456790 ABC #%? . ()

1
Noha Elprince

Travailler à mon rythme en Python Fluent (Ramalho) - hautement recommandé

onlyascii = ''.join([s for s in data if ord(s) < 127])
onlymatch = ''.join([s for s in data if s in
              'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'])
0
Matthew Dunn