Основная причина, по которой ваш опубликованный код дает сбой (даже с использованием только символов ascii!), Заключается в том, что re.split () не будет разбиваться при совпадении с нулевой шириной . r'\b'
соответствует нулевым символам:
>>> re.split(r'\b', 'foo-BAR_baz')
['foo-BAR_baz']
>>> re.split(r'\W+', 'foo-BAR_baz')
['foo', 'BAR_baz']
>>> re.split(r'[\W_]+', 'foo-BAR_baz')
['foo', 'BAR', 'baz']
Кроме того, вам необходимо flags=re.UNICODE
, чтобы убедиться, что используются определения Unicode \b
и \W
и т. Д. И использование str()
там, где вы это сделали, в лучшем случае не нужно.
Так что это вообще не было проблемой Unicode. Однако некоторые авторы пытались решить эту проблему как проблему Unicode с разной степенью успеха ... вот мое мнение о проблеме Unicode:
Общее решение проблемы такого рода заключается в следовании стандартному простому совету, который применим ко всем текстовым задачам: Как можно раньше расшифруйте свой ввод из строк байтов в строки юникода. Делать всю обработку в юникоде. Закодируйте выводимый юникод в байтовые строки как можно позже.
Итак: byte_string.decode('utf8').isupper()
- это путь. Следует избегать таких хаков, как byte_string.decode('ascii', 'ignore').isupper()
; они могут быть всеми (сложными, ненужными, подверженными сбоям) - см. ниже.
Некий код:
# coding: ascii
import unicodedata
tests = (
(u'\u041c\u041e\u0421\u041a\u0412\u0410', True), # capital of Russia, all uppercase
(u'R\xc9SUM\xc9', True), # RESUME with accents
(u'R\xe9sum\xe9', False), # Resume with accents
(u'R\xe9SUM\xe9', False), # ReSUMe with accents
)
for ucode, expected in tests:
print
print 'unicode', repr(ucode)
for uc in ucode:
print 'U+%04X %s' % (ord(uc), unicodedata.name(uc))
u8 = ucode.encode('utf8')
print 'utf8', repr(u8)
actual1 = u8.decode('utf8').isupper() # the natural way of doing it
actual2 = u8.decode('ascii', 'ignore').isupper() # @jathanism
print expected, actual1, actual2
Вывод из Python 2.7.1:
unicode u'\u041c\u041e\u0421\u041a\u0412\u0410'
U+041C CYRILLIC CAPITAL LETTER EM
U+041E CYRILLIC CAPITAL LETTER O
U+0421 CYRILLIC CAPITAL LETTER ES
U+041A CYRILLIC CAPITAL LETTER KA
U+0412 CYRILLIC CAPITAL LETTER VE
U+0410 CYRILLIC CAPITAL LETTER A
utf8 '\xd0\x9c\xd0\x9e\xd0\xa1\xd0\x9a\xd0\x92\xd0\x90'
True True False
unicode u'R\xc9SUM\xc9'
U+0052 LATIN CAPITAL LETTER R
U+00C9 LATIN CAPITAL LETTER E WITH ACUTE
U+0053 LATIN CAPITAL LETTER S
U+0055 LATIN CAPITAL LETTER U
U+004D LATIN CAPITAL LETTER M
U+00C9 LATIN CAPITAL LETTER E WITH ACUTE
utf8 'R\xc3\x89SUM\xc3\x89'
True True True
unicode u'R\xe9sum\xe9'
U+0052 LATIN CAPITAL LETTER R
U+00E9 LATIN SMALL LETTER E WITH ACUTE
U+0073 LATIN SMALL LETTER S
U+0075 LATIN SMALL LETTER U
U+006D LATIN SMALL LETTER M
U+00E9 LATIN SMALL LETTER E WITH ACUTE
utf8 'R\xc3\xa9sum\xc3\xa9'
False False False
unicode u'R\xe9SUM\xe9'
U+0052 LATIN CAPITAL LETTER R
U+00E9 LATIN SMALL LETTER E WITH ACUTE
U+0053 LATIN CAPITAL LETTER S
U+0055 LATIN CAPITAL LETTER U
U+004D LATIN CAPITAL LETTER M
U+00E9 LATIN SMALL LETTER E WITH ACUTE
utf8 'R\xc3\xa9SUM\xc3\xa9'
False False True
Единственные отличия от Python 3.x - это синтаксический принцип - принцип (вся обработка выполняется в юникоде) остается тем же.