2010-01-28 87 views
9

我在unicode中有一个字符串,我需要返回前N个字符。 我这样做:返回unicode字符串的前N个字符

result = unistring[:5] 

但当然unicode字符串的长度=字符的长度! 任何想法?唯一的解决办法是使用重新?

编辑:更多信息

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

returns->?

我认为unicode字符串是两个字节(char),这就是为什么会发生这种情况。如果我做的:

result = unistring[:2] 

我得到

M

这是正确的, 所以,我就应该总是片* 2,或者我应该转换成什么?

+0

你确定你有一个实际的Unicode字符串,而不是(说)与UTF-8数据的字节串?如果是这样,你如何定义'角色'? (unicode字符串是代码点字符串(在UCS-4版本中)或codeunits。) – 2010-01-28 11:03:03

+1

来自我们的主机:http://www.joelonsoftware.com/articles/Unicode.html – Will 2010-01-28 12:52:10

+0

请问,请不要。这在这里并不适用。 – Joey 2010-01-28 12:59:39

回答

6

由于Python 3.0之前的历史原因,不幸的是有两种字符串类型。 byte strings (str) and Unicode strings (unicode)

在Python 3.0中统一之前,有两种声明字符串文字的方法:unistring = "Μεταλλικα"这是一个字节字符串,而unistring = u"Μεταλλικα"是一个Unicode字符串。

您在看到?时的原因result = unistring[:1]是因为Unicode文本中的某些字符无法在非Unicode字符串中正确表示。如果您曾经使用过旧的电子邮件客户端,并收到希腊等国的朋友发来的电子邮件,则可能会遇到此类问题。

所以在Python 2.x中,如果你需要处理Unicode,你必须明确地做到这一点。看看这个在Python中处理Unicode的介绍:Unicode HOWTO

+0

“Μεταλλικα”不是ASCII字符串。它是用于保存脚本的编码中的字节字符串。 – 2010-01-29 11:15:42

+2

你是对的标记将这些字符串称为字符串而不是ASCII字符串更正确,我已经更新了相应的答案。我真正想表达的是,ASCII文本(或等效字节字符串,取决于计算机上的代码页)是唯一可以用字符串安全处理的东西。 – 2010-01-29 12:48:39

+1

Unicode HOWTO链接已死亡 – jeremyvillalobos 2016-02-10 14:18:34

8

当你说:

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

没有 unicode字符串做。你有一个字节串(推测是)UTF-8。这不是一回事。 unicode字符串是Python中的一个单独的数据类型。通过使用正确的编码解码字节串得到统一:

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

或使用Unicode文本在源文件中使用正确的编码声明

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

Unicode字符串会做你想要的时候,你是什么做unistring[:5]

+0

您还需要在.decode()示例之前使用“#coding:utf-8”,并且该文件必须实际保存在utf-8中。解码脚本时,Python 2.x默认为ASCII。任何使用非ASCII字符都需要#coding行声明用于保存文件的编码。 – 2010-01-29 11:20:14

+1

在Python 2.5及更高版本中,您需要使用非ASCII内容的任何源文件的编码声明,是的。 (在此之前,它只是一个警告)。然而,编码声明不会改变代码的含义,因为它只是字节中的字节。 – 2010-01-29 13:23:43

+1

-1这是不正确的ü“一些Unicode测试”[:5]可能会给非法序列,因为UTF-16是可变宽度编码,所以切割“Unicode”字符串不正确,因为切割utf-8字符串 – Artyom 2010-01-29 13:43:56

4

对任何类型的“Unicode字符串”都没有正确的直接方法。

即使Python“Unicode”UTF-16字符串也有可变长度字符,所以不能用ustring [:5]来切割。因为一些Unicode代码点可能使用多于一个的“字符”,即代理对。

所以,如果你想减少5个代码点(注意,这些字符),所以你可以对文本进行分析,看​​和http://en.wikipedia.org/wiki/UTF-16定义。所以你需要使用一些掩码来找出边界。

此外,你还没有得到字符。因为例如。单词“שָלוֹם” - 希伯来语中的和平“沙洛姆”由4个字符和6个代码点字母“shin”,元音“a”字母“lamed”,字母“vav”和元音“o”以及最终字母“mem”组成。

所以字符不是码点

对于大多数西方语言而言,其中带有变音符号的字母可能表示为两个代码点。搜索“unicode标准化”示例。

所以...如果你真的需要5个首字符,你必须使用ICU库等工具。例如,Python的ICU库提供字符边界迭代器。