2016-11-30 3 views
0

Versuch erwartet, eine Python regex zu schreiben, die eine Zeichenfolge, die ausPython alphanumerischer Unicode regex arbeitet nicht als

  • jedes Unicode alphanumerischen Zeichen (einschließlich Kombinationszeichen)
  • beliebige Anzahl von Leerzeichen validieren
  • Eine beliebige Anzahl von Unterstrichen
  • Eine beliebige Anzahl von Strichen
  • Eine beliebige Anzahl von Perioden

Mein Test-Strings:

9 Melodía.de_la-montaña 
9 Melodía.de_la-montaña 

oder als String mit ascii() produziert Literale:

str1 = '9 Melod\xeda.de_la-monta\xf1a' 
str2 = '9 Melodi\u0301a.de_la-montan\u0303a' 

Diese identisch aussehen, aber nicht, man wird normalisiert und die andere verwendet die Kombination von Zeichen für die Beugungen .

Hier ist mein erster Stich:

import re 

reg = re.compile("^[\w\.\- ]+$", re.IGNORECASE) 
re.search(reg, str1) # None 
re.search(reg, str2) # None 

Wenn ich die Positions-Qualifikation zu entfernen und verwende findall statt search ich Listen wie diese ['9 Melodi', 'a.de_la-montan', 'a'] oder ['9 Melod', 'a.de_la-monta', 'a'].

Ich habe sogar versucht re.compile("^[\w\.\- ]+$", re.IGNORECASE | re.UNICODE), obwohl das in Python 3 nicht notwendig sein sollte, richtig?

für eine Antwort Bei der Suche habe ich this question und this one und this one und this one gefunden, aber sie sind alle alt, beschäftigen sich mit Python 2 und scheinen darauf hinzudeuten, dass der Regex ich soll Arbeit schrieb. Die regex-Dokumentation von python 3.5 erwähnt, dass \w Unicode entsprechen sollte, aber keine konkreten Beispiele für Nicht-ASCII-Text bietet.

Wie passe ich die gewünschten Zeichenfolgen an?

+0

Ist die Zeichenfolge zuerst eine Option zu normalisieren? 'unicodedata.normalize ('NFC', etwas)? Die Fragen, auf die Sie verlinken, treffen nicht auf Ihre Situation zu, nicht weil sie in Python 2 sind (die Regex-Engine ist im Grunde die gleiche zwischen 2 und 3, außer 're.UNICODE' ist jetzt die Standardeinstellung), aber weil sie nicht sind versuchen, kombinierte Zeichen zu vergleichen. –

+0

Können Sie bitte auch die 'print (ascii (str1))' und 'print (ascii (str2))' Versionen der Strings mit angeben? Auf diese Weise können wir sie einfach kopieren, ohne sich um die richtigen Kodierungen kümmern zu müssen. –

+0

@MartijnPieters Ich könnte, und meine erste Test-String * ist * normalisiert, aber die Regex stimmt immer noch nicht richtig. –

Antwort

0

Ihre erste Probe, str1, passt gut; \w enthält alle Unicode-Zeichen, einschließlich lateinische Zeichen mit Akzenten.

Sie können Ihre Saiten auf die kombinierte Form mit unicodedata.normalize(), verwenden Sie die NFC Form normalisieren:

>>> import re 
>>> import unicodedata 
>>> str1 = '9 Melod\xeda.de_la-monta\xf1a' 
>>> str2 = '9 Melodi\u0301a.de_la-montan\u0303a' 
>>> reg = re.compile("^[\w\.\- ]+$") 
>>> reg.search(str1) 
<_sre.SRE_Match object; span=(0, 23), match='9 Melodía.de_la-montaña'> 
>>> reg.search(str2) is None 
True 
>>> reg.search(unicodedata.normalize('NFC', str2)) 
<_sre.SRE_Match object; span=(0, 23), match='9 Melodía.de_la-montaña'> 

Beachten Sie, dass die re.IGNORECASE Flagge nicht benötigt wird, ist \w über Fall nicht.

+0

Getestet und funktioniert. Ich warte nur darauf zu akzeptieren. –

Verwandte Themen