104 votes

Normalisation d'Unicode

Existe-t-il un moyen standard, en Python, de normaliser une chaîne unicode, de sorte qu'elle ne comprenne que les entités unicodes les plus simples qui peuvent être utilisées pour la représenter ?

Je veux dire, quelque chose qui traduirait une séquence comme ['LATIN SMALL LETTER A', 'COMBINING ACUTE ACCENT'] à ['LATIN SMALL LETTER A WITH ACUTE'] ?

Vous voyez où est le problème :

>>> import unicodedata
>>> char = "á"
>>> len(char)
1
>>> [ unicodedata.name(c) for c in char ]
['LATIN SMALL LETTER A WITH ACUTE']

Mais maintenant :

>>> char = "a"
>>> len(char)
2
>>> [ unicodedata.name(c) for c in char ]
['LATIN SMALL LETTER A', 'COMBINING ACUTE ACCENT']

Je pourrais, bien sûr, itérer sur tous les caractères et faire des remplacements manuels, etc., mais ce n'est pas efficace, et je suis presque sûr que je manquerais la moitié des cas particuliers, et que je ferais des erreurs.

145voto

Martijn Pieters Points 271458

Le site unicodedata Le module offre un .normalize() fonction que vous voulez normaliser à la forme NFC. Un exemple utilisant le même U+0061 LATIN SMALL LETTER - U+0301 A COMBINING ACUTE ACCENT combinaison et U+00E1 LATIN SMALL LETTER A WITH ACUTE les points de code que vous avez utilisés :

>>> print(ascii(unicodedata.normalize('NFC', '\u0061\u0301')))
'\xe1'
>>> print(ascii(unicodedata.normalize('NFD', '\u00e1')))
'a\u0301'

(J'ai utilisé le ascii() fonction ici pour s'assurer que les points de code non-ASCII sont imprimés en utilisant la syntaxe d'échappement, rendant les différences claires).

NFC, ou "Normal Form Composed", renvoie des caractères composés, NFD, "Normal Form Decomposed", des caractères décomposés et combinés.

Les formulaires additionnels NFKC et NFKD traitent des points de code de compatibilité ; par ex. U+2160 ROMAN NUMERAL ONE est en fait la même chose que U+0049 LATIN CAPITAL LETTER I mais présents dans la norme Unicode pour rester compatibles avec les encodages qui les traitent séparément. L'utilisation de la forme NFKC ou NFKD, en plus de composer ou décomposer des caractères, remplacera également tous les caractères de "compatibilité" par leur forme canonique.

Voici un exemple utilisant le U+2167 ROMAN NUMERAL EIGHT L'utilisation de la forme NFKC le remplace par une séquence de caractères ASCII. V y I des personnages :

>>> unicodedata.normalize('NFC', '\u2167')
''
>>> unicodedata.normalize('NFKC', '\u2167')
'VIII'

Notez qu'il n'y a aucune garantie que les formes composées et décomposées soient commutatives ; normaliser un caractère combiné en forme NFC, puis reconvertir le résultat en forme NFD ne donne pas toujours la même séquence de caractères. La norme Unicode maintient une liste d'exceptions ; les caractères de cette liste sont composables, mais pas décomposables en leur forme combinée, pour diverses raisons. Consultez également la documentation sur la fonction Table d'exclusion de la composition .

11voto

SLaks Points 391154

Oui, il y a .

unicodedata.normalize(form, unistr)

Vous devez sélectionner l'un des quatre formes de normalisation .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X