Python check if utf-8 string ist Großbuchstaben

Ich habe Probleme mit .isupper (), wenn ich einen utf-8 codierten String habe. Ich habe eine Menge Textdateien, die ich in xml umwandle. Während der Text sehr variabel ist, ist das Format statisch. Worte in allen Caps sollten in <title> tags und alles andere <p> eingehüllt werden. Es ist also wesentlich komplexer, aber das sollte für meine Frage genügen.

Mein Problem ist, dass dies eine utf-8 Datei ist. Dies ist ein Muss, da es in der endgültigen Ausgabe einige viele nicht-englische Zeichen gibt. Dies kann Zeit sein, um ein kurzes Beispiel zu geben:

InputText.txt

FORTSETZEN

Bacon ipsum dolor sitzen amet streifen steak t-bone chicken, irure ground runde nostrud aute pancetta schinken hock incididunt aliqua. Dolore kurze Lende Ex Huhn, Chuck Drumstick ut Hamburger ut andouille. In laborum eiusmod kurze lende, spare ribs enim kugelspitzenwurst. Tenderloin ut Konsequenz Flanke. Letztes offizielles Lendenfilet. In pancetta tun, ut dolore t-bone sint Schweinefleisch pariatur dolore Hühnchen Übungen. Nostrud Ribeye Schwanz, ut ullamco Hirsch Mollit Schweinekotelett proident consectetur fugiat reprehenderit officia ut tri-tip.

GewünschtOutput

  <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> 

Beispielcode

  #!/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() 

Letztlich ist es ziemlich einfach, ich würde Kritik oder Anregungen auf meinen Code akzeptieren. Wer würde nicht Besonders bin ich unglücklich mit str(tokens[i]) vielleicht gibt es einen besseren Weg, um durch eine Liste von Strings zu schleifen?

Aber der Zweck dieser Frage ist es, herauszufinden, die effizienteste Weg zu überprüfen, ob ein utf-8-String wird aktiviert. Vielleicht sollte ich in die Handlung eines Regex dafür schauen.

Beachten Sie, ich habe diesen Code nicht ausgeführt und es kann nicht richtig laufen. Ich habe die Teile vom Arbeitscode abgeholt und kann etwas falsch gemacht haben. Alert mich und ich werde es korrigieren. Endlich bemerke ich nicht mit lxml

3 Solutions collect form web for “Python check if utf-8 string ist Großbuchstaben”

Der primäre Grund, dass Ihr veröffentlichter Code fehlschlägt (auch mit nur ascii Zeichen!) Ist, dass re.split () nicht auf eine Null-Breite-Übereinstimmung aufgeteilt wird . r'\b' entspricht null Zeichen:

 >>> 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'] 

Außerdem benötigen Sie flags=re.UNICODE um sicherzustellen, dass Unicode-Definitionen von \b und \W etc verwendet werden. Und mit str() wo du warst, ist am besten unnötig.

Also war es nicht wirklich ein Unicode-Problem an sich überhaupt. Allerdings versuchten einige Antwortende, es als Unicode-Problem anzusprechen, mit unterschiedlichen Erfolgsgraden … hier ist mein Unicode-Problem:

Die allgemeine Lösung für diese Art von Problem ist, die Standard-Sumpf-einfache Beratung, die für alle Textprobleme gilt folgen: Decodieren Sie Ihre Eingabe von Bytestrings zu Unicode-Strings so früh wie möglich. Führen Sie alle Verarbeitung in Unicode. Kodiere deine Ausgabe Unicode so schnell wie möglich in Byte Strings.

Also: byte_string.decode('utf8').isupper() ist der Weg zu gehen. Hacks wie byte_string.decode('ascii', 'ignore').isupper() sind zu vermeiden; Sie können alle (kompliziert, unnötig, fehleranfällig) sein – siehe unten.

Einige Code:

 # 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 

Ausgabe von 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 

Die einzigen Unterschiede mit Python 3.x sind syntaktisch – das Prinzip (alle Verarbeitung in Unicode) bleibt gleich.

Wie ein Kommentar oben illustriert, ist es nicht wahr für jeden Charakter, dass einer der Schecks islower () vs isupper () wird immer wahr und die anderen false. Unified Han-Charaktere werden zum Beispiel als "Briefe" betrachtet, sind aber nicht Kleinbuchstaben, nicht Großbuchstaben und kein Titel.

So sollten Ihre erklärten Anforderungen, um Groß- und Kleinbuchstaben anders zu behandeln, geklärt werden. Ich nehme an, die Unterscheidung ist zwischen Großbuchstaben und allen anderen Zeichen. Vielleicht spaltet das die Haare, aber du redest hier von nicht-englischem Text.

Zuerst empfehle ich die Verwendung von Unicode-Strings (die Unicode () eingebaut) exklusiv für die String Verarbeitung Teile Ihres Codes. Disziplinieren Sie Ihren Verstand, um an die "regelmäßigen" Saiten als Byte-Strings zu denken, denn das ist genau das, was sie sind. Alle String-Literale, die nicht so geschrieben sind, sind Byte-Strings.

Diese Codezeile dann:

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

würde werden:

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

Sie testen auch tokens[i].isupper() anstatt str(tokens[i]).isupper() . Basierend auf dem, was Sie gepostet haben, scheint es wahrscheinlich, dass andere Teile Ihres Codes geändert werden müssen, um mit Zeichenfolgen anstelle von Byte-Strings zu arbeiten.

Einfache Lösung. Ich denke

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

wird

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

Dann bin ich in der Lage, ohne Notwendigkeit für str() oder unicode() so weit wie ich sagen kann.

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

Das Wort token und das re.split auf Wortgrenzen ist Vermächtnis von, als ich mit nltk Anfang dieser Woche verwirrte. Aber letztlich verarbeite ich Linien, keine Token / Worte. Das kann sich ändern. Aber jetzt scheint das zu funktionieren Ich werde diese Frage jetzt offen lassen, in der Hoffnung auf alternative Lösungen und Kommentare.

  • Konvertiere GBK in utf8 string in python
  • Python 3 CSV-Datei, die UnicodeDecodeError: 'utf-8' Codec kann nicht decode Byte Fehler, wenn ich drucken
  • Überprüfen Sie auf gültige utf8 Zeichenfolge in Python
  • Erhöhtes Verständnis von Unicode in Python (2.7)
  • UTF-8 und os.listdir ()
  • Drucken auf UTF-8 codierte Datei mit plattformabhängigen Zeilenumbrüchen?
  • Encoding Fehler in Django auf Heroku
  • UTF-8 Kodierung in Python
  • Wie gibt man eine utf-8 String-Liste wie es in Python ist?
  • Wie Normalisierung Unicode-Encoding für iso-8859-15 Umwandlung in Python?
  • UnicodeDecodeError im PyCharm-Debugger
  • Python ist die beste Programmiersprache der Welt.