Какой самый быстрый способ снять и заменить документ с высокими символами Юникода с помощью Python?

Я хочу заменить из большого документа все высокие символы юникода, такие как акцентированные Es, левые и правые кавычки и т. Д., С «нормальными» аналогами в низком диапазоне, такими как регулярные «E» и прямые кавычки. Мне нужно довольно часто выполнять это на очень большом документе. Я вижу пример этого в том, что, на мой взгляд, может быть perl: http://www.designmeme.com/mtplugins/lowdown.txt

Есть ли быстрый способ сделать это в Python без использования s.replace (…). Replace (…). Replace (…) …? Я попробовал это на нескольких символах, чтобы заменить, и снятие документа стало очень медленным.

  • обработка текста - производительность python vs perl
  • EDIT, моя версия кода unutbu, которая, похоже, не работает:

    # -*- coding: iso-8859-15 -*- import unidecode def ascii_map(): data={} for num in range(256): h=num filename='x{num:02x}'.format(num=num) try: mod = __import__('unidecode.'+filename, fromlist=True) except ImportError: pass else: for l,val in enumerate(mod.data): i=h<<8 i+=l if i >= 0x80: data[i]=unicode(val) return data if __name__=='__main__': s = u'“fancy“fancy2' print(s.translate(ascii_map())) 

  • Сценарий Python для преобразования из UTF-8 в ASCII
  • Строка Python печатает как
  • Преобразование int в ASCII и обратно в Python
  • Как преобразовать двоичную строку в строку ascii в python?
  • Словарь испортил имя ключа
  • feedparser выходит из строя во время запуска скрипта, но не может воспроизводиться в интерактивной консоли python
  • 5 Solutions collect form web for “Какой самый быстрый способ снять и заменить документ с высокими символами Юникода с помощью Python?”

     # -*- encoding: utf-8 -*- import unicodedata def shoehorn_unicode_into_ascii(s): return unicodedata.normalize('NFKD', s).encode('ascii','ignore') if __name__=='__main__': s = u"éèêàùçÇ" print(shoehorn_unicode_into_ascii(s)) # eeeaucC 

    Обратите внимание, как любезно указывает @Mark Tolonen, метод выше удаляет некоторые символы, такие как ß '' "". Если приведенный выше код усекает символы, которые вы хотите перевести, вам, возможно, придется использовать метод translate строки, чтобы вручную исправить эти проблемы. Другой вариант – использовать unidecode (см . Ответ JF Sebastian ).

    Когда у вас есть большая строка юникода, использование метода translate будет намного быстрее, чем использование метода replace .

    Edit: unidecode имеет более полное отображение кодовых unidecode Unicode в ascii. Тем не менее, unidecode.unidecode через строковый символ за символом (в цикле Python), который медленнее, чем использование метода translate .

    Следующая вспомогательная функция использует unidecode данных unidecode и метод translate для достижения более высокой скорости, особенно для длинных строк.

    В моих тестах с текстовыми файлами 1-6 Мбайт использование ascii_map примерно в 4-6 раз быстрее, чем unidecode.unidecode .

     # -*- coding: utf-8 -*- import unidecode def ascii_map(): data={} for num in range(256): h=num filename='x{num:02x}'.format(num=num) try: mod = __import__('unidecode.'+filename, fromlist=True) except ImportError: pass else: for l,val in enumerate(mod.data): i=h<<8 i+=l if i >= 0x80: data[i]=unicode(val) return data if __name__=='__main__': s = u"éèêàùçÇ" print(s.translate(ascii_map())) # eeeaucC 

    Edit2: Rhubarb, если # -*- encoding: utf-8 -*- вызывает SyntaxError, попробуйте # -*- encoding: cp1252 -*- . Какая кодировка для объявления зависит от того, какую кодировку использует текстовый редактор для сохранения файла. Linux имеет тенденцию использовать utf-8 и (кажется, возможно) Windows имеет тенденцию к cp1252.

    Нет такой вещи, как «высокий символ ascii». Набор символов ASCII ограничен порядковым номером (128).

    В стороне, это FAQ. Вот один ответ . В общем, вам следует ознакомиться с str.translate () и unicode.translate () – очень удобно для нескольких подстановок одиночных байтов / символов. Остерегайтесь ответов, в которых упоминается только трюк unicodedata.normalize (); это всего лишь одна часть решения.

    Обновление : принятый в настоящее время ответ сдувает символы, которые не имеют разложения, как указал Марк Толонен. Кажется, что не хватает знаний о том, что может использовать unicode.translate() . Он МОЖЕТ перевести один символ на несколько символов. Вот результат с help(unicode.translate) :

    S.translate (таблица) -> unicode

    Верните копию строки S, где все символы были сопоставлены с помощью данной таблицы перевода, которая должна быть отображением ордеров Unicode в ординалы Unicode, строки Unicode или None. Неизменяемые символы остаются нетронутыми. Символы, сопоставленные None, удаляются.

    Вот пример:

     >>> u"Gau\xdf".translate({0xdf: u"ss"}) u'Gauss' >>> 

    Вот таблица исправлений из решения, на которое я указал:

     CHAR_REPLACEMENT = { # latin-1 characters that don't have a unicode decomposition 0xc6: u"AE", # LATIN CAPITAL LETTER AE 0xd0: u"D", # LATIN CAPITAL LETTER ETH 0xd8: u"OE", # LATIN CAPITAL LETTER O WITH STROKE 0xde: u"Th", # LATIN CAPITAL LETTER THORN 0xdf: u"ss", # LATIN SMALL LETTER SHARP S 0xe6: u"ae", # LATIN SMALL LETTER AE 0xf0: u"d", # LATIN SMALL LETTER ETH 0xf8: u"oe", # LATIN SMALL LETTER O WITH STROKE 0xfe: u"th", # LATIN SMALL LETTER THORN } 

    Это можно легко расширить, чтобы удовлетворить причудливые кавычки и другие символы не-латинского-1, найденные в cp1252 и братьях и сестрах.

    Я считаю, что unicodedata не работает для причудливых котировок. Вы можете использовать Unidecode в этом случае:

     import unidecode print unidecode.unidecode(u"ß''“”") # -> ss''"" 

    Если unicodedata.normalize (), предложенный ~unubtu , не выполняет трюк, например, если вы хотите больше контролировать отображение, вы должны изучить
    str.translate ()
    наряду с str.maketrans () , утилитой для создания таблицы карт, str.translate эффективен и удобен для такого типа перевода.
    В Python 2.x и для строк unicode нужно использовать unicode.translate (), а не str.translate () и трюк, подобный тому, который показан ниже в фрагменте кода, вместо maketrans (). (спасибо Джону Мачину за это!)

    Эти методы также доступны в Python 3.x, например, в документации Python 3.1.2 (по какой-то причине я мысленно заметил, что это может измениться в Python 3.x). Конечно, под Python 3 все строки являются строками unicode, но это другая проблема.

     #Python 3.1 >>> intab = 'àâçêèéïîôù' >>> outtab = 'aaceeeiiou' >>> tmap = str.maketrans(intab, outtab) >>> s = "à la fête de l'été, où il fait bon danser, les Français font les drôles" >>> s "à la fête de l'été, où il fait bon danser, les Français font les drôles" >>> s.translate(tmap) "a la fete de l'ete, ou il fait bon danser, les Francais font les droles" >>> #Python 2.6 >>> intab = u'àâçêèéïîôù' >>> outtab = u'aaceeeiiou' >>> s = u"à la fête de l'été, où il fait bon danser, les Français font les drôles" >>> #note the trick to replace maketrans() since for unicode strings the translation >>> # map expects integers (unicode ordinals) not characters. >>> tmap = dict(zip(map(ord, intab), map(ord, outtab))) >>> s.translate(tmap) u"a la fete de l'ete, ou il fait bon danser, les Francais font les droles" >>> 

    Вот решение, которое обрабатывает латинские символы (на основе потока usenet 2003 года):

     >>> accentstable = str.join("", map(chr, range(192))) + "AAAAAAACEEEEIIIIDNOOOOOxOUUUUYTsaaaaaaaceeeeiiiidnooooo/ouuuuyty" >>> import string >>> s = u"éèêàùçÇ" >>> print string.translate(s.encode('latin1', 'ignore'), accentstable) eeeaucC 

    Некоторые из отображений не идеальны, например, карты Thorn для T, а не Th, но они выполняют терпимую работу.

    Python - лучший язык программирования в мире.