Заменить не-ASCII символов с пробелом
мне нужно заменить все символы, отличные от ASCII (x00-x7F) пробелом. Я удивлен, что это не мертво-легко в Python, если я ничего не упускаю. Следующая функция просто удаляет все символы, отличные от ASCII:
def remove_non_ascii_1(text):
return ''.join(i for i in text if ord(i)<128)
и этот заменяет символы, отличные от ASCII, количеством пробелов в соответствии с количеством байтов в кодовой точке символа (т. е. –
символ заменяется 3 места):
def remove_non_ascii_2(text):
return re.sub(r'[^x00-x7F]',' ', text)
как я могу заменить все символы, отличные от ASCII, с одним пробелом?
Of the множество of как так вопросы, нет адрес символ замена as против to зачистки, и дополнительно адресуйте все не-ascii персонажи не конкретный персонаж.
6 ответов
код ''.join()
выражение фильтрация, удаляя что-либо не-ASCII; вместо этого вы можете использовать условное выражение:
return ''.join([i if ord(i) < 128 else ' ' for i in text])
это обрабатывает символы один за другим и по-прежнему будет использовать одно пространство на символ заменен.
ваше регулярное выражение должно просто заменить подряд символы без ASCII с пробелом:
re.sub(r'[^\x00-\x7F]+',' ', text)
Примечание +
там.
для вас получите наиболее похожее представление вашей исходной строки, которую я рекомендую модуль unidecode:
from unidecode import unidecode
def remove_non_ascii(text):
return unidecode(unicode(text, encoding = "utf-8"))
затем вы можете использовать его в строку:
remove_non_ascii("Ceñía")
Cenia
на символ обработка, используйте строки Unicode:
PythonWin 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] on win32.
>>> s='ABC马克def'
>>> import re
>>> re.sub(r'[^\x00-\x7f]',r' ',s) # Each char is a Unicode codepoint.
'ABC def'
>>> b = s.encode('utf8')
>>> re.sub(rb'[^\x00-\x7f]',rb' ',b) # Each char is a 3-byte UTF-8 sequence.
b'ABC def'
но обратите внимание, что у вас все равно будет проблема, если ваша строка содержит разложенные символы Юникода (например, отдельный символ и сочетание знаков акцента):
>>> s = 'mañana'
>>> len(s)
6
>>> import unicodedata as ud
>>> n=ud.normalize('NFD',s)
>>> n
'mañana'
>>> len(n)
7
>>> re.sub(r'[^\x00-\x7f]',r' ',s) # single codepoint
'ma ana'
>>> re.sub(r'[^\x00-\x7f]',r' ',n) # only combining mark replaced
'man ana'
Если символ замены может быть '?- вместо места я бы предложил ... --2-->:
"""Test the performance of different non-ASCII replacement methods."""
import re
from timeit import timeit
# 10_000 is typical in the project that I'm working on and most of the text
# is going to be non-ASCII.
text = 'Æ' * 10_000
print(timeit(
"""
result = ''.join([c if ord(c) < 128 else '?' for c in text])
""",
number=1000,
globals=globals(),
))
print(timeit(
"""
result = text.encode('ascii', 'replace').decode()
""",
number=1000,
globals=globals(),
))
результаты:
0.7208260721400134
0.009975979187503592
Как насчет этого?
def replace_trash(unicode_string):
for i in range(0, len(unicode_string)):
try:
unicode_string[i].encode("ascii")
except:
#means it's non-ASCII
unicode_string=unicode_string[i].replace(" ") #replacing it with a single space
return unicode_string
как родной и эффективный подход, вам не нужно использовать ord
или любой цикл над символами. Просто Закодируйте с ascii
и игнорировать ошибки.
следующее просто удалит символы, отличные от ascii:
new_string = old_string.encode('ascii',errors='ignore')
теперь, если вы хотите заменить удаленные персонажи просто сделайте следующее:
final_string = new_string + b' ' * (len(old_string) - len(new_string))