Как удалить символы, отличные от ASCII, но оставить периоды и пробелы с помощью Python?

Я работаю с файлом .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(), чтобы оставить пробелы и периоды? Я предполагаю, что это не слишком сложно, но я не могу понять.

Ответ 1

Вы можете отфильтровать все символы из строки, которые нельзя распечатать, используя 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
!"#$%&\'()*+,-./:;<=>[email protected][\\]^_'{|}~ \t\n\r\x0b\x0c

ОБНОВЛЕНИЕ: В Python 3 фильтр будет возвращать итерацию. Правильный способ получить строку назад:

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

Ответ 2

Легкий способ изменить на другой кодек - это использовать 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

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

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

Ответ 3

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

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

Смотрите другие примеры здесь fooobar.com/questions/40584/...

Ответ 4

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

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

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

this is line 1
this is line 2

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

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

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

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

Ответ 5

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

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

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

Ответ 6

Вы можете использовать следующий код для удаления неанглийских букв:

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

Это вернет

123456790 ABC#%?.()

Ответ 7

Работаем мой путь через 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'])