Python3和结合变音符号

时间:2019-02-20 08:44:11

标签: python-3.x unicode diacritics

我在python3中遇到了Unicode问题,而且我似乎不明白为什么会这样。

symbol= "ῇ̣"
print(len(symbol))
>>>>2

这封信来自一个单词:ἐ̣ν̣τ̣ῇ̣[αὐτ]ῇ,在这里我结合了变音标记。我想在Python 3中进行统计分析并将结果存储在数据库中,事实是我还在文本中存储了字符的位置(索引)。数据库应用程序正确地将示例中的符号变量视为一个字符,而Python将其视为两个-从而删除了整个索引。

该项目要求我保留变音符号,因此我不能简单地忽略它们或在字符串上进行.replace("combining diacritical mark","")

由于Python3将unicode作为字符串的默认设置,因此我对此有些傻眼。

我曾尝试使用希腊语重音https://pypi.org/project/greek-accentuation/中的base()strip()strip_length()方法,但这无济于事。

项目要求是:

  • 检测属于字符的字母(确定)
  • 存储字符串位置(需要在数据库中突出显示)(NotOK)
  • 能够处理混合在一个字符串中的多种语言/字母。 (确定)
  • 遍历CSV输入。 (确定)
  • 忽略一组预定义的字符串(确定)
  • 忽略匹配某些条件的字符串集(确定)

这是此项目的简化代码:

# -*- coding: utf-8 -*-
import csv
from alphabet_detector import AlphabetDetector
ad = AlphabetDetector()
with open("tbltext.csv", "r", encoding="utf8") as txt:
    data = csv.reader(txt)
    for row in data:
        text = row[1]
        ### Here I have some string manipulation (lowering everything, replacing the predefined set of strings by equal-length '-',...)
        ###then I use the ad-module to detect the language by looping over my characters, this is where it goes wrong.
        for letter in text:
            lang = ad.detect_alphabet(letter)

如果我使用单词:ἐ̣ν̣τ̣ῇ̣[αὐτ]ῇ作为forloop的示例;我的结果是:

>>> word = "ἐ̣ν̣τ̣ῇ̣[αὐτ]ῇ"
>>> for letter in word:
...     print(letter)
...
ἐ
̣
ν
̣
τ
̣
ῇ
̣
[
α
ὐ
τ
]
ῇ

如何使Python将带有组合变音标记的字母视为一个字母,而不是使其分别打印字母和变音标记?

1 个答案:

答案 0 :(得分:1)

该字符串的长度为2,所以这是正确的:两个代码点:

>>> list(hex(ord(c)) for c in symbol)
['0x1fc7', '0x323']
>>> list(unicodedata.name(c) for c in symbol)
['GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI', 'COMBINING DOT BELOW']

因此,您不应使用len来计算字符。

您可以算出非组合字符,所以:

>>> import unicodedata
>>> len(''.join(ch for ch in symbol if unicodedata.combining(ch) == 0))
1

发件人:How do I get the "visible" length of a combining Unicode string in Python?(但我将其移植到python3)。

但这也不是最佳解决方案,具体取决于计算字符的范围。我认为在您的情况下就足够了,但是字体可以将字符合并为连字。在某些语言上,它们是视觉上新的字符(并且有很大不同)(并且不像西方语言中的连字)。

最后一条评论:我认为您应该规范化字符串。使用上面的代码,在这种情况下并不重要,但是在其他情况下,您可能会得到不同的结果。尤其是如果有人使用战斗性字符(例如,以mu为单位,或使用Eszett代替真正的希腊字符)。