Как я могу удалить не-ASCII символы, но оставить точки и пробелы, используя Python? - PullRequest
81 голосов
/ 31 декабря 2011

Я работаю с файлом .txt. Я хочу строку текста из файла без символов не ASCII. Тем не менее, я хочу оставить пробелы и периоды. В настоящее время я тоже их снимаю. Вот код:

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

Как мне изменить onlyascii (), чтобы оставить пробелы и точки? Я думаю, что это не слишком сложно, но я не могу понять это.

Ответы [ 6 ]

157 голосов
/ 31 декабря 2011

Вы можете отфильтровать все символы из строки, которые нельзя распечатать, используя string.printable , например:

>>> 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 на моей машине содержит:

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c
74 голосов
/ 25 августа 2013

Простой способ перейти на другой кодек - использовать encode () или decode ().В вашем случае вы хотите конвертировать в ASCII и игнорировать все символы, которые не поддерживаются.Например, шведская буква å не является символом 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

Редактировать:

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 (декодировать и кодировать в обратном порядке)

>>> "hej d\xe5".decode("ascii", errors="ignore").encode()
'hej d'
22 голосов
/ 23 февраля 2016

Согласно @artfulrobot, это должно быть быстрее, чем filter и lambda:

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

См. Больше примеров здесь http://stackoverflow.com/questions/20078816/replace-non-ascii-characters-with-a-single-space/20079244#20079244

7 голосов
/ 01 января 2012

Ваш вопрос неоднозначен; первые два предложения, взятые вместе, подразумевают, что вы считаете, что пробел и «точка» не являются символами ASCII. Это неверно Все символы, такие как ord (char) <= 127, являются символами ASCII. Например, ваша функция исключает эти символы! "# $% & \ '() * +, -. /, Но включает несколько других, например [] {}. </p>

Пожалуйста, сделайте шаг назад, подумайте немного и отредактируйте свой вопрос, чтобы сообщить нам, что вы пытаетесь сделать, не упоминая слово ASCII и почему вы думаете, что символы, такие как ord (char)> = 128, игнорируются. Также: какая версия Python? Какова кодировка ваших входных данных?

Обратите внимание, что ваш код считывает весь входной файл в виде одной строки, а ваш комментарий («отличное решение») к другому ответу подразумевает, что вам не нужны новые строки в ваших данных. Если ваш файл содержит две строки, подобные этой:

this is line 1
this is line 2

результат будет 'this is line 1this is line 2' ... это то, что вы действительно хотите?

Более широкое решение будет включать:

  1. лучшее название для функции фильтра, чем onlyascii
  2. признание того, что функция фильтра просто должна возвращать истинное значение, если аргумент должен быть сохранен:

    def filter_func(char):
        return char == '\n' or 32 <= ord(char) <= 126
    # and later:
    filtered_data = filter(filter_func, data).lower()
    
1 голос
/ 31 декабря 2011

Если вы хотите печатать символы ascii, вы, вероятно, должны исправить свой код так:

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

это эквивалентно string.printable (ответ от @jterrace), за исключением отсутствия возвратов и вкладок ('\ t', '\ n', '\ x0b', '\ x0c' и '\ r '), но не соответствует диапазону по вашему вопросу

0 голосов
/ 14 сентября 2017

Пробираюсь через Fluent Python (Ramalho) - очень рекомендуется. Понимание списка, вдохновленное главой 2:

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