Возврат первых N символов строки Unicode - PullRequest
11 голосов
/ 28 января 2010

У меня есть строка в Unicode, и мне нужно вернуть первые N символов. Я делаю это:

result = unistring[:5]

но, конечно, длина строки в юникоде! = Длина символов. Есть идеи? Единственное решение - использовать re?

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

unistring = "Μεταλλικα" #Metallica written in Greek letters
result = unistring[:1]

возвращает->?

Я думаю, что строки в юникоде - это два байта (символа), поэтому это происходит. Если я сделаю:

result = unistring[:2]

Я получаю

M

что правильно, Итак, я всегда должен нарезать * 2 или я должен преобразовать во что-то?

Ответы [ 3 ]

7 голосов
/ 28 января 2010

К сожалению, по историческим причинам до Python 3.0 существует два типа строк. строки байтов (str) и строки Unicode (unicode) .

До объединения в Python 3.0 существует два способа объявления строкового литерала: unistring = "Μεταλλικα", который является строкой байтов, и unistring = u"Μεταλλικα", который является строкой Unicode.

Причина, по которой высмотрите ?, когда вы делаете result = unistring[:1], потому что некоторые символы в вашем тексте Unicode не могут быть правильно представлены в строке не-Unicode.Вы, вероятно, сталкивались с подобными проблемами, если когда-либо использовали очень старый почтовый клиент и получали электронные письма от друзей в таких странах, как, например, Греция.

Так что в Python 2.x, если вам нужно работать с Unicode, вам нужносделать это явно.Взгляните на это введение по работе с Unicode в Python: Unicode HOWTO

7 голосов
/ 28 января 2010

Когда вы говорите:

unistring = "Μεταλλικα" #Metallica written in Greek letters

У вас нет строки Unicode. У вас есть строка в (предположительно) UTF-8. Это не одно и то же. Строка Unicode - это отдельный тип данных в Python. Вы получаете юникод, декодируя строки байтов, используя правильную кодировку:

unistring = "Μεταλλικα".decode('utf-8')

или с использованием литерала unicode в исходном файле с правильным объявлением кодировки

# coding: UTF-8
unistring = u"Μεταλλικα"

Строка Unicode будет делать то, что вы хотите, когда вы делаете unistring[:5].

4 голосов
/ 29 января 2010

Не существует правильного прямого подхода с любым типом «строки Unicode».

Даже строка Python "Unicode" UTF-16 имеет символы переменной длины, поэтому вы не можете просто вырезать с помощью ustring [: 5]. Поскольку некоторые точки кода Unicode могут использовать более одного «символа», то есть суррогатные пары.

Поэтому, если вы хотите сократить 5 кодовых точек (обратите внимание, что это не символов ), чтобы вы могли проанализировать текст, см. http://en.wikipedia.org/wiki/UTF-8 и http://en.wikipedia.org/wiki/UTF-16 определений. Поэтому вам нужно использовать битовые маски для определения границ.

Также вы все еще не получаете персонажей. Потому что например. Слово «שָלוֹם» - мир на иврите «шалом» состоит из 4 символов и 6 кодовых точек: буква «shin», гласный «a», буква «lamed», буква «vav» и гласный «o» и конечная буква «mem».

То есть символ не кодовая точка .

То же самое для большинства западных языков, где буква с диакритическими знаками может быть представлена ​​как две кодовые точки. Найдите, например, «нормализация Юникода».

Итак ... Если вам действительно нужно 5 первых символов, вам нужно использовать такие инструменты, как библиотека ICU. Например, есть библиотека ICU для Python, которая обеспечивает итератор границ символов.

...