2010-01-28 24 views
9

Tengo una cadena en Unicode y debo devolver los primeros N caracteres. estoy haciendo esto:Devolviendo los primeros N caracteres de una cadena Unicode

result = unistring[:5] 

pero por supuesto la longitud de las cadenas Unicode = longitud de caracteres!. Alguna idea? La única solución es usar re?

Edición: Más información

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

VUELTA a>?

Creo que las cadenas Unicode son dos bytes (char), por eso sucede esto. Si hago:

result = unistring[:2] 

me sale

M

lo cual es correcto, Por lo tanto, debería siempre cortar * 2 o debería convertir en algo?

+0

¿Estás seguro de que tienes una cadena Unicode real y no (por ejemplo) una cadena de bytes con datos UTF-8? Si es así, ¿cómo defines 'personaje'? (cadenas Unicode son cadenas de puntos de código (en compilaciones UCS-4) o codeunits.) –

+1

Desde nuestro host: http://www.joelonsoftware.com/articles/Unicode.html – Will

+0

Will, por favor no. Eso no es realmente aplicable aquí. – Joey

Respuesta

6

Desafortunadamente, por razones históricas anteriores a Python 3.0, hay dos tipos de cadenas. byte strings (str) and Unicode strings (unicode).

Antes de la unificación en Python 3.0 hay dos formas de declarar una cadena literal: unistring = "Μεταλλικα" que es una cadena de bytes y unistring = u"Μεταλλικα" que es una cadena unicode.

La razón por la que ve ? cuando hace result = unistring[:1] es porque algunos de los caracteres en su texto Unicode no se pueden representar correctamente en la cadena que no es unicode. Probablemente haya visto este tipo de problema si alguna vez utilizó un cliente de correo electrónico realmente viejo y recibió correos electrónicos de amigos en países como Grecia, por ejemplo.

Por lo tanto, en Python 2.x si necesita manejar Unicode, tiene que hacerlo explícitamente. Eche un vistazo a esta introducción para tratar con Unicode en Python: Unicode HOWTO

+0

"Μεταλλικα" no es una cadena ASCII. Es una cadena de bytes en la codificación utilizada para guardar el script. –

+2

Tiene razón Marque que es más correcto referirse a estos como cadenas de bytes en lugar de cadenas ASCII. He actualizado la respuesta en consecuencia. Lo que realmente estaba tratando de expresar era que el texto ASCII (o una cadena de bytes equivalente según las páginas de códigos en su computadora) es lo único que puede manipularse con seguridad con cadenas de bytes. –

+1

El enlace CÓMO Unicode está muerto – jeremyvillalobos

8

Al decir:

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

Usted no tienen una cadena Unicode. Usted tiene una cadena de bytes en (supuestamente) UTF-8. Eso no es lo mismo. Una cadena Unicode es un tipo de datos separado en Python. Se obtiene Unicode mediante la decodificación de cadenas de bytes utilizando la codificación correcta:

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

o utilizando el Unicode literal en un archivo de origen con la derecha declaración de codificación

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

La cadena Unicode hará lo que quiera, cuando do unistring[:5].

+0

También necesitará "#coding: utf-8" antes del ejemplo .decode(), y el archivo debe estar realmente guardado en utf-8. Python 2.x se establece de manera predeterminada en ASCII al decodificar scripts. Cualquier uso de caracteres que no sean ASCII requiere que la línea #coding declare la codificación utilizada para guardar el archivo. –

+1

En Python 2.5 y posterior necesita la declaración de codificación en cualquier archivo fuente con contenido no ASCII, sí. (Antes de eso, es solo una advertencia). Sin embargo, la declaración de codificación no cambiará el significado del código, ya que solo se trata de bytes en una cadena de bytes. –

+1

-1 Esto no es correcto u "Some Unicode test" [: 5] Puede dar una secuencia ilegal, porque UTF-16 es una codificación de ancho variable, por lo que cortar cadena "Unicode" no es correcto como cortar cadena utf-8 – Artyom

4

No hay un enfoque directo correcto con cualquier tipo de "cadena Unicode".

Incluso la cadena de caracteres "Unicode" UTF-16 de Python tiene caracteres de longitud variable, por lo que no puede cortar con la función ustring [: 5]. Debido a que algunos puntos de código Unicode pueden usar más de un "carácter", es decir, pares de sustitución.

Así que si usted quiere cortar 5 puntos de código (tenga en cuenta estos no son caracteres) por lo que puede analizar el texto, véase http://en.wikipedia.org/wiki/UTF-8 y http://en.wikipedia.org/wiki/UTF-16 definiciones. Entonces necesitas usar algunas máscaras de bits para descubrir los límites.

También todavía no obtienes caracteres. Porque, por ejemplo. Palabra "שָלוֹם" - paz en hebreo "Shalom" consta de 4 caracteres y 6 puntos de código letra "shin", vocal "a" letra "lamed", letra "vav" y vocal "o" y letra final "mem".

Así carácter no es código punto.

Lo mismo para la mayoría de los idiomas occidentales donde una letra con signos diacríticos se puede representar como dos puntos de código. Busque, por ejemplo, "normalización Unicode".

Así que ... Si realmente necesita 5 primeros caracteres, debe usar herramientas como la biblioteca de ICU. Por ejemplo, hay una biblioteca de ICU para Python que proporciona caracteres de límite de iterador.

Cuestiones relacionadas