8

不是单词边界,这是可以解决的。

例子:

#!/usr/bin/env python3  
text = 'เมื่อแรกเริ่ม'  
for char in text:  
    print(char)  

这会产生:

อ<br> แ<br> ร<br> ก<br> เ

这显然不是所需的输出。有任何想法吗?

文本的可移植表示是:

text = u'\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e41\u0e23\u0e01\u0e40\u0e23\u0e34\u0e48\u0e21'
4

3 回答 3

11

tl;dr:使用\X正则表达式提取用户感知的字符:

>>> import regex # $ pip install regex
>>> regex.findall(u'\\X', u'เมื่อแรกเริ่ม')
['เ', 'มื่', 'อ', 'แ', 'ร', 'ก', 'เ', 'ริ่', 'ม']

虽然我不会泰语,但我会一点法语。

考虑这封信è。在 Python shell 中让ss2等于:è

>>> 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

但从视觉上看,两种编码都会产生 'letter' è。这称为字形,或最终用户认为的一个字符。

您可以演示您看到的相同循环行为:

>>> [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

但是,这不适用于许多非拉丁语言。处理可能是组成单个字素的多个代码点的 unicode 字符串的一种简单方法是使用正则表达式引擎,该引擎通过支持\X. 不幸的是,Python 的包含re模块没有。

建议的替代品regex确实支持\X

>>> import regex
>>> text = 'เมื่อแรกเริ่ม'
>>> regex.findall(r'\X', text)
['เ', 'มื่', 'อ', 'แ', 'ร', 'ก', 'เ', 'ริ่', 'ม']
>>> len(_)
9
于 2015-05-07T15:41:02.293 回答
3

我不能完全复制,但这里是你脚本的一个轻微修改版本,在 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)
เ
มื่
อ
แ
ร
ก
เ
ริ่
ม
>>> 
于 2015-05-07T14:59:00.460 回答
2

为了澄清以前的答案,您遇到的问题是缺少的字符是“组合字符” - 元音和变音符号必须与其他字符组合才能正确显示。没有标准的方式来单独显示这些字符,尽管最常见的约定是使用虚线圆圈作为空辅音,如 Serge Ballesta 的回答所示。

那么问题是,对于您的应用程序,每个元音和变音符号是否被视为一个单独的字符,或者您是否希望通过“打印单元格”来分隔,如 Serge 的回答所示?

顺便说一句,在正常使用中,除非在键入更长的单词的过程中,否则不应在没有跟随辅音的情况下显示前导元音 SARA E 和 SARA AE。

有关更多信息,请参阅 Thai API Consortium (TAPIC) 发布的 WTT 2.0 标准,该标准定义了如何组合、显示字符以及如何处理错误。

于 2017-07-20T13:34:01.503 回答