разбиение строки юникода на слова - PullRequest
9 голосов
/ 02 сентября 2011

Я пытаюсь разбить строку Unicode на слова (упрощенно), например:

print re.findall(r'(?u)\w+', "раз два три")

То, что я ожидаю увидеть, это:

['раз','два','три']

Но то, что я действительно получаюis:

['\xd1', '\xd0', '\xd0', '\xd0', '\xd0\xb2\xd0', '\xd1', '\xd1', '\xd0']

Что я делаю не так?

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

Если я использую u перед строкой:

print re.findall(r'(?u)\w+', u"раз два три")

Я получаю:

[u'\u0440\u0430\u0437', u'\u0434\u0432\u0430', u'\u0442\u0440\u0438']

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

Аааа, и мне кажется, что я должен был сначала прочитать документы:

 print re.findall(r'(?u)\w+', u"раз два три")[0].encode('utf-8')

Даст мне:

раз

Просто чтобы убедиться, это звучит как правильный подход к нему?

1 Ответ

6 голосов
/ 02 сентября 2011

На самом деле вы получаете то, что ожидаете в случае Unicode. Вы только думаете, что это не из-за странного побега из-за того, что вы смотрите на reprs строк, а не на вывод их значений без экранирования. (Это только то, как списки отображаются.)

>>> words = [u'\u0440\u0430\u0437', u'\u0434\u0432\u0430', u'\u0442\u0440\u0438'] 
>>> for w in words:
...     print w # This uses the terminal encoding -- _only_ utilize interactively
... 
раз
два
три
>>> u'раз' == u'\u0440\u0430\u0437'
True

Не пропустите мое замечание о печати этих строк Юникода. Обычно, если вы собираетесь отправить их на экран, в файл, по проводам и т. Д., Вам необходимо вручную закодировать их в правильную кодировку. Когда вы используете print, Python пытается использовать кодировку вашего терминала, но он может сделать это только при наличии терминала. Поскольку вы, как правило, не знаете, существует ли он, вы должны полагаться только на это в интерактивном интерпретаторе и всегда явно кодировать в нужную кодировку.

В этом простом подходе разделения на пустые пространства вы можете вообще не использовать регулярные выражения, а просто использовать метод unicode.split.

>>> u"раз два три".split()
[u'\u0440\u0430\u0437', u'\u0434\u0432\u0430', u'\u0442\u0440\u0438']

Ваш верхний (bytestring) пример не работает, потому что re в основном предполагает, что все байтовые строки являются ASCII по своей семантике, а ваш - нет. Использование юникодных строк позволяет вам получить правильную семантику для вашего алфавита и локали. Насколько это возможно, текстовые данные всегда должны быть представлены с использованием unicode, а не str.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...