Проверка python, если строка utf-8 в верхнем регистре

У меня возникают проблемы с .isupper (), когда у меня есть строка с кодировкой utf-8. У меня много текстовых файлов, которые я конвертирую в xml. Хотя текст очень переменный, формат является статическим. слова во всех шапках должны быть обернуты тегами <title> и все остальное <p> . Это значительно сложнее, чем это, но это должно быть достаточно для моего вопроса.

Моя проблема в том, что это файл utf-8. Это необходимо, так как в конечном выпуске будет несколько неанглийских символов. Возможно, настало время представить краткий пример:

inputText.txt

ПРОДОЛЖИТЬ

Бэкон ipsum dolor sit amet strip steak t-bone chicken, irure ground round nostrud aute pancetta ham hock incididunt aliqua. Долора короткая поясница из курицы, патрон-барабанная утварь гамбургер-ут и. В трусике eiusmod короткая поясница, запасные ребра enim ball tip колбаса. Вырезка из бока. Tempor officia sirloin duis. В pancetta do, ut dolore t-bone sint свинина pariatur dolore куриное упражнение. Nostrud ribeye tail, ut ullamco Оленина Mollit Свинина Chop Противоположный consectetur fugiat reprehenderit officia ut tri-tip.

DesiredOutput

  <title>RÉSUMÉ</title> <p>Bacon ipsum dolor sit amet strip steak t-bone chicken, irure ground round nostrud aute pancetta ham hock incididunt aliqua. Dolore short loin ex chicken, chuck drumstick ut hamburger ut andouille. In laborum eiusmod short loin, spare ribs enim ball tip sausage. Tenderloin ut consequat flank. Tempor officia sirloin duis. In pancetta do, ut dolore t-bone sint pork pariatur dolore chicken exercitation. Nostrud ribeye tail, ut ullamco venison mollit pork chop proident consectetur fugiat reprehenderit officia ut tri-tip. </p> 

Образец кода

  #!/usr/local/bin/python2.7 # yes this is an alt-install of python import codecs import sys import re from xml.dom.minidom import Document def main(): fn = sys.argv[1] input = codecs.open(fn, 'r', 'utf-8') output = codecs.open('desiredOut.xml', 'w', 'utf-8') doc = Documents() doc = parseInput(input,doc) print>>output, doc.toprettyxml(indent=' ',encoding='UTF-8') def parseInput(input, doc): tokens = [re.split(r'\b', line.strip()) for line in input if line != '\n'] #remove blank lines for i in range(len(tokens)): # THIS IS MY PROBLEM. .isupper() is never true. if str(tokens[i]).isupper(): title = doc.createElement('title') tText = str(tokens[i]).strip('[\']') titleText = doc.createTextNode(tText.title()) doc.appendChild(title) title.appendChild(titleText) else: p = doc.createElement('p') pText = str(tokens[i]).strip('[\']') paraText = doc.createTextNode(pText) doc.appendChild(p) p.appenedChild(paraText) return doc if __name__ == '__main__': main() 

в конечном счете, это довольно прямолинейно, я бы принял критические замечания или предложения по моему коду. Кто бы не стал? В частности, я недоволен str(tokens[i]) возможно, есть лучший способ перебрать список строк?

Но цель этого вопроса состоит в том, чтобы выяснить наиболее эффективный способ проверить, является ли строка utf-8 заглавной. Возможно, я должен изучить создание регулярного выражения для этого.

Заметьте, я не запускал этот код, и он может работать не так. Я взял детали из рабочего кода и, возможно, что-то не понял. Оповестите меня, и я исправлю это. наконец, заметьте, что я не использую lxml

3 Solutions collect form web for “Проверка python, если строка utf-8 в верхнем регистре”

Основная причина, по которой ваш опубликованный код терпит неудачу (даже с только символами 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 – синтаксические – принцип (вся обработка в юникоде) остается неизменным.

Как показывает один комментарий выше, для каждого символа неверно, что одна из проверок islower () vs isupper () всегда будет истиной, а другая ложью. Например, символы Unified Han считаются «буквами», но не строчными, а не прописными, а не надписными.

Поэтому необходимо уточнить ваши заявленные требования, чтобы трактовать текст в верхнем и нижнем регистре по-разному. Я предполагаю, что это различие между прописными буквами и всеми другими символами. Возможно, это расщепление волос, но вы говорите здесь о неанглоязычном тексте.

Во-первых, я рекомендую использовать строки Unicode (встроенный unicode ()) исключительно для частей обработки строк вашего кода. Дисциплинируйте свой ум, чтобы думать о «регулярных» строках как байтовых строках, потому что это именно то, что они есть. Все строковые литералы, не написанные u"like this" являются байтовыми строками.

Затем эта строка кода:

 tokens = [re.split(r'\b', line.strip()) for line in input if line != '\n'] 

станет:

 tokens = [re.split(u'\\b', unicode(line.strip(), 'UTF-8')) for line in input if line != '\n'] 

Вы также будете тестировать tokens[i].isupper() а не str(tokens[i]).isupper() . На основании того, что вы опубликовали, кажется вероятным, что другие части вашего кода нужно будет изменить для работы с символьными строками вместо байтовых строк.

Простое решение. я думаю

 tokens = [re.split(r'\b', line.strip()) for line in input if line != '\n'] #remove blank lines 

становится

 tokens = [line.strip() for line in input if line != '\n'] 

то я могу пойти без необходимости в str() или unicode() Насколько я могу судить.

 if tokens[i].isupper(): #do stuff 

Слово токен и re.split на границах слов является наследием, когда я уже возился с nltk на этой неделе. Но в конечном счете я обрабатываю линии, а не токены / слова. Это может измениться. но пока это, похоже, работает. Сейчас я оставлю этот вопрос открытым, в надежде на альтернативные решения и комментарии.

  • Как преобразовать строку из CP-1251 в UTF-8?
  • Python и UTF-8: что-то путать
  • Несмотря на кодировку utf8, некоторые символы не могут быть распознаны
  • python unicode: Как я могу судить, нужно ли декодировать строку в utf-8?
  • Почему Python настаивает на использовании ascii?
  • Сделать utf8 доступным для чтения в файле
  • Опасности sys.setdefaultencoding ('utf-8')
  • Кодировка символов Python Европейские акценты
  • Python - лучший язык программирования в мире.