不是通过字边界,这是可以解决的。
示例:
#!/usr/bin/env python3
text = 'เมื่อแรกเริ่ม'
for char in text:
print(char)
这产生:
เ
ม
อ
แ
ร
ก
เ
嗯
ม
这显然不是理想的输出。有什么想法吗?
文本的可移植表示是:
text = u'\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e41\u0e23\u0e01\u0e40\u0e23\u0e34\u0e48\u0e21'
答案 0 :(得分:8)
tl; dr:使用\X
正则表达式提取用户感知的字符:
>>> import regex # $ pip install regex
>>> regex.findall(u'\\X', u'เมื่อแรกเริ่ม')
['เ', 'มื่', 'อ', 'แ', 'ร', 'ก', 'เ', 'ริ่', 'ม']
虽然我不懂泰语,但我知道一点法语。
考虑字母è
。在Python shell中让s
和s2
等于è
:
>>> s
'è'
>>> s2
'è'
同一封信? oui,以视觉上的法语发言人。对于计算机,没有:
>>> s==s2
False
您可以使用è
的实际代码点创建相同的字母,也可以使用字母e
并添加添加该重音字符的组合代码点。他们有不同的编码:
>>> s.encode('utf-8')
b'\xc3\xa8'
>>> s2.encode('utf-8')
b'e\xcc\x80'
不同长度:
>>> len(s)
1
>>> len(s2)
2
但在视觉上,两种编码都会产生字母' è
。这称为grapheme,或最终用户认为的一个字符。
您可以演示您所看到的相同循环行为:
>>> [c for c in s]
['è']
>>> [c for c in s2]
['e', '̀']
您的字符串中包含多个组合字符。因此,你眼中的9字形字符泰语字符串成为Python的13个字符串。
法语解决方案是根据Unicode equivalence标准化字符串:
>>> from unicodedata import normalize
>>> normalize('NFC', s2) == s
True
但这对许多非拉丁语言不起作用。处理组成single grapheme的多个代码点的unicode字符串的简单方法是使用正则表达式引擎,通过支持\X
来正确处理此问题。不幸的是,Python还包括re
模块doesn't。
建议的替换regex确实支持\X
:
>>> import regex
>>> text = 'เมื่อแรกเริ่ม'
>>> regex.findall(r'\X', text)
['เ', 'มื่', 'อ', 'แ', 'ร', 'ก', 'เ', 'ริ่', 'ม']
>>> len(_)
9
答案 1 :(得分:2)
我无法完全重现,但这里是您脚本的略微修改版本,在Windows7 64系统上的IDLE 3.4输出:
>>> for char in text:
print(char, hex(ord(char)), unicodedata.name(char),'-',
unicodedata.category(char), '-', unicodedata.combining(char), '-',
unicodedata.east_asian_width(char))
เ 0xe40 THAI CHARACTER SARA E - Lo - 0 - N
ม 0xe21 THAI CHARACTER MO MA - Lo - 0 - N
ื 0xe37 THAI CHARACTER SARA UEE - Mn - 0 - N
่ 0xe48 THAI CHARACTER MAI EK - Mn - 107 - N
อ 0xe2d THAI CHARACTER O ANG - Lo - 0 - N
แ 0xe41 THAI CHARACTER SARA AE - Lo - 0 - N
ร 0xe23 THAI CHARACTER RO RUA - Lo - 0 - N
ก 0xe01 THAI CHARACTER KO KAI - Lo - 0 - N
เ 0xe40 THAI CHARACTER SARA E - Lo - 0 - N
ร 0xe23 THAI CHARACTER RO RUA - Lo - 0 - N
ิ 0xe34 THAI CHARACTER SARA I - Mn - 0 - N
่ 0xe48 THAI CHARACTER MAI EK - Mn - 107 - N
ม 0xe21 THAI CHARACTER MO MA - Lo - 0 - N
>>>
我真的不知道这些角色是什么 - 我的泰语非常差:-) - 但它表明:
len(text)
(13
)如果是预期输出,则证明您的问题不在Python中,而是在显示它的控制台上有更多问题。您应该尝试将输出重定向到文件,然后在支持泰语字符的unicode编辑器中打开该文件。
如果预期的输出只有9个字符,那就是如果你不想分解组合字符,并且如果没有其它组合规则应该考虑,你可以使用类似的东西:
def Thaidump(t):
old = None
for i in t:
if unicodedata.category(i) == 'Mn':
if old is not None:
old = old + i
else:
if old is not None:
print(old)
old = i
print(old)
那样:
>>> Thaidump(text)
เ
มื่
อ
แ
ร
ก
เ
ริ่
ม
>>>
答案 2 :(得分:2)
为了澄清之前的答案,您遇到的问题是缺少的字符是“组合字符” - 元音和变音符号必须与其他字符组合才能正确显示。没有标准的方法可以自己显示这些字符,尽管最常见的惯例是使用虚线圆作为空辅音,如Serge Ballesta的回答所示。
那么问题是,对于你的应用程序,每个元音和变音符被认为是一个单独的字符,或者你是否希望用“印刷单元”分开,如Serge的回答所示?
顺便说一下,在正常使用情况下,除了在输入更长的单词的过程中,不应在没有辅助辅音的情况下显示主元音SARA E和SARA AE。
有关更多信息,请参阅Thai API Consortium(TAPIC)发布的WTT 2.0标准,该标准定义了如何组合,显示字符以及如何处理错误。