2010-01-28 6 views
9

J'ai une chaîne en Unicode et j'ai besoin de retourner les N premiers caractères. Je fais ceci:Renvoyer les N premiers caractères d'une chaîne unicode

result = unistring[:5] 

mais bien sûr, la longueur des chaînes unicode = longueur de caractères!. Des idées? La seule solution utilise re?

Modifier: Plus d'infos

unistring = "Μεταλλικα" #Metallica written in Greek letters 
result = unistring[:1] 

returns->?

Je pense que les chaînes unicode sont deux octets (char), c'est pourquoi cette chose arrive. Si je fais:

result = unistring[:2] 

Je reçois

M

qui est correct, Alors, dois-je couper toujours * 2 ou devrais-je convertir en quelque chose?

+0

Etes-vous sûr d'avoir une chaîne unicode réelle, et pas (disons) un bytestring avec des données UTF-8? Si oui, comment définissez-vous le «caractère»? (Les chaînes Unicode sont des chaînes de codes (dans les versions UCS-4) ou des codeunits.) –

+1

De notre hôte: http://www.joelonsoftware.com/articles/Unicode.html – Will

+0

Will, s'il vous plaît pas. Ce n'est pas vraiment applicable ici. – Joey

Répondre

6

Malheureusement, pour des raisons historiques antérieures à Python 3.0, il existe deux types de chaînes. byte strings (str) and Unicode strings (unicode).

Avant l'unification dans Python 3.0, il existe deux façons de déclarer un littéral de chaîne: unistring = "Μεταλλικα" qui est une chaîne d'octets et unistring = u"Μεταλλικα" qui est une chaîne unicode. La raison pour laquelle vous voyez ? lorsque vous faites result = unistring[:1] est que certains caractères de votre texte Unicode ne peuvent pas être correctement représentés dans la chaîne non-unicode. Vous avez probablement vu ce genre de problème si vous avez déjà utilisé un client de messagerie très ancien et reçu des courriels d'amis dans des pays comme la Grèce par exemple.

Donc, dans Python 2.x si vous avez besoin de gérer Unicode, vous devez le faire explicitement. Jetez un oeil à cette introduction à traiter Unicode en Python: Unicode HOWTO

+0

"Μεταλλικα" n'est pas une chaîne ASCII. C'est une chaîne d'octets dans l'encodage utilisé pour enregistrer le script. –

+2

Vous avez raison Mark il est plus correct de se référer à ces chaînes comme des octets plutôt que des chaînes ASCII, j'ai mis à jour la réponse en conséquence. Ce que j'essayais vraiment d'exprimer, c'est que le texte ASCII (ou une chaîne d'octets équivalente en fonction des pages de code sur votre ordinateur) est la seule chose qui peut être manipulée en toute sécurité avec des chaînes d'octets. –

+1

Le lien Unicode HOWTO est mort – jeremyvillalobos

8

Quand vous dites:

unistring = "Μεταλλικα" #Metallica written in Greek letters 

Vous n'ont pas une chaîne unicode. Vous avez un bytestring dans (probablement) UTF-8. Ce n'est pas la même chose. Une chaîne unicode est un type de données distinct en Python. Vous obtenez unicode en décodant les chaînes d'octets en utilisant le bon encodage:

unistring = "Μεταλλικα".decode('utf-8') 

ou en utilisant le unicode littéral dans un fichier source avec la déclaration de codage droit

# coding: UTF-8 
unistring = u"Μεταλλικα" 

La chaîne unicode fera ce que vous voulez quand vous faire unistring[:5].

+0

Vous aurez besoin de "#coding: utf-8" avant l'exemple .decode(), et le fichier doit être sauvegardé dans utf-8. Python 2.x utilise par défaut ASCII lors du décodage des scripts. Toute utilisation de caractères non ASCII nécessite que la ligne #coding déclare l'encodage utilisé pour enregistrer le fichier. –

+1

En Python 2.5 et plus tard, vous avez besoin de la déclaration de codage sur n'importe quel fichier source avec des contenus non-ASCII, oui. (Auparavant, c'est juste un avertissement.) La déclaration de codage ne changera cependant pas la signification du code, puisqu'il ne s'agit que d'octets dans un bytestring. –

+1

-1 Ceci n'est pas correct u "Unicode test" [: 5] Peut donner une séquence illégale, car UTF-16 est un encodage à largeur variable, donc couper une chaîne "Unicode" n'est pas correct comme une chaîne utf-8 – Artyom

4

Il n'y a pas d'approche directe correcte avec n'importe quel type de "chaîne Unicode".

Même Python La chaîne UTF-16 "Unicode" a des caractères de longueur variable, vous ne pouvez donc pas couper avec ustring [: 5]. Parce que certains points de code Unicode peuvent utiliser plus d'un "caractère", c'est-à-dire des paires de substitution.

Donc, si vous voulez couper 5 points de code (notez ce ne sont pas caractères) afin que vous puissiez analyser le texte, voir http://en.wikipedia.org/wiki/UTF-8 et http://en.wikipedia.org/wiki/UTF-16 définitions. Vous devez donc utiliser des masques de bits pour déterminer les limites.

Vous ne recevez toujours pas de caractères. Parce que par exemple. Mot "שָלוֹם" - paix en hébreu "Shalom" se compose de 4 caractères et 6 points de code lettre "shin", voyelle "a" lettre "lamed", lettre "vav" et voyelle "o" et lettre finale "mem".

Donc le caractère n'est pas le code.

Idem pour la plupart des langues occidentales où une lettre avec des signes diacritiques peut être représentée par deux points de code. Recherchez par exemple "normalisation unicode". Donc, si vous avez vraiment besoin de 5 premiers caractères, vous devez utiliser des outils comme la bibliothèque ICU. Par exemple, il existe une bibliothèque ICU pour Python qui fournit l'itérateur de limite de caractères.

Questions connexes