按字符拆分泰语文本

jos*_*ski 5 python unicode python-3.x thai

不是通过单词边界,这是可以解决的.

例:

#!/usr/bin/env python3  
text = '?????????????'  
for char in text:  
    print(char)  
Run Code Online (Sandbox Code Playgroud)

这将产生:






这显然不是理想的输出.有任何想法吗?

可移植的文本表示形式是:

text = u'\u0e40\u0e21\u0e37\u0e48\u0e2d\u0e41\u0e23\u0e01\u0e40\u0e23\u0e34\u0e48\u0e21'
Run Code Online (Sandbox Code Playgroud)

daw*_*awg 8

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

>>> import regex # $ pip install regex
>>> regex.findall(u'\\X', u'?????????????')
['?', '???', '?', '?', '?', '?', '?', '???', '?']
Run Code Online (Sandbox Code Playgroud)

虽然我不懂泰语,但我知道一点法语.

考虑一下这封信è.让我们ss2等于è在Python外壳:

>>> s
'è'
>>> s2
'è'
Run Code Online (Sandbox Code Playgroud)

同一封信?oui,以视觉上的法语发言人.对于电脑,没有:

>>> s==s2
False
Run Code Online (Sandbox Code Playgroud)

您可以使用实际代码点创建相同的字母,也可以è通过获取字母e并添加添加该重音字符的组合代码点.他们有不同的编码:

>>> s.encode('utf-8')
b'\xc3\xa8'
>>> s2.encode('utf-8')
b'e\xcc\x80'
Run Code Online (Sandbox Code Playgroud)

并且不同的长度:

>>> len(s)
1
>>> len(s2)
2
Run Code Online (Sandbox Code Playgroud)

但在视觉上,两种编码都会产生"字母" è.这就是所谓的字形,或最终用户认为一个字符是什么.

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

>>> [c for c in s]
['è']
>>> [c for c in s2]
['e', '?']
Run Code Online (Sandbox Code Playgroud)

你的字符串中有几个组合字符.因此,你眼中的9字形字符泰语字符串成为Python的13个字符串.

法语解决方案是基于Unicode 等价来规范化字符串:

>>> from unicodedata import normalize
>>> normalize('NFC', s2) == s
True
Run Code Online (Sandbox Code Playgroud)

但这对许多非拉丁语言不起作用.处理组成单个字形的多个代码点的unicode字符串的简单方法是使用正则表达式引擎,通过支持正确处理此问题\X.不幸的是,Python包含的re模块还没有.

建议的替换,正则表达式确实支持\X:

>>> import regex
>>> text = '?????????????'
>>> regex.findall(r'\X', text)
['?', '???', '?', '?', '?', '?', '?', '???', '?']
>>> len(_)
9
Run Code Online (Sandbox Code Playgroud)