发出打印字符串的单个字母

时间:2016-11-29 07:48:59

标签: python unicode python-3.5

我正在尝试打印单个字母,它可以正常使用英文和中文拼音但是当我尝试使用其他字母时,我也会使用unicode字符(Diacritic)

考虑这个词

महाभूकम्पले

当我尝试用键盘箭头键和它分开时空间这是महाभूकम्पले的结果,就像英文单词“示例

一样
E X A M P L E

 म हा भू क म्प ले

现在,当我尝试运行python脚本以使用此代码自动执行此操作时

data= 'महाभूकम्पले'
index = 0
while index < len(data):
    letter = data[index]
    print (letter)
    index = index + 1

我的结果是:(它已将所有变音符号分开)

म
ह
ा
भ
ू
क
म
्
प
ल
े

我需要的是这个

म 
हा 
भू 
क 
म्प 
ले

2 个答案:

答案 0 :(得分:2)

您的数据确实包含11个字符:

>>> data = 'महाभूकम्पले'
>>> len(data)
11

那是因为那里有几个变音字符,当打印时,它们与前面的字符组合在一起。您必须检测这些并将它们一起打印出来。

说起来容易做起来难。

Unicode数据库有各种拼写可以组合的字符的方法。在西方字母表中,您有像cedille(ç上的卷曲)或重音符号或tremas(áä)这样的变音符号,在Unicode中可以表示为1和2字符,这些表单称为规范组合正常形式规范分解正常形式,您可以使用unicodedata.normalize() function在两种形式之间进行转换。< / p>

但是对于梵文剧本来说,没有复合形式;变音符号总是单独指定。相反,对于这些字符,换行符记录在lb表中;当需要插入换行符时应该如何处理这些。对于梵文变音符号,行为设置为CM组合标记Unicode Line Breaking Algorithm中描述了确切含义。 CM被描述为:

  

分类: CM
  描述性名称:结合标记
  示例:组合标记,控制代码
  行为:禁止角色与前一个角色之间的换行符

问题是lb模块无法提供unicodedata数据表。

您必须使用LineBreaks.txt table作为来源构建自己的表,然后测试该表中的下一个字符是否为CM并将其打印在同一行上。

只提取CM代码点:

cm_chars = set()
with open('LineBreak.txt') as lbtable:
    for line in lbtable:
        if ';CM' not in line:
            continue
        chars, category = line.partition(' ')[0].split(';')
        if category != 'CM':
            continue
        chars = chars.split('..')
        for codepoint in range(int(chars[0], 16), int(chars[-1], 16) + 1):
            cm_chars.add(chr(codepoint))

然后使用它来检测是否要在同一行上打印下一个字符:

>>> data = 'महाभूकम्पले'
>>> index = 0
>>> while index < len(data):
...     letters = data[index]
...     while index + 1 < len(data) and data[index + 1] in cm_chars:
...         letters += data[index + 1]
...         index += 1
...     print(letters)
...     index += 1
...
म
हा
भू
क
म्
प
ले

但这只涵盖了CM字符。您可能还想要覆盖GL(胶水)字符,这些字符附加到前面的序列中的下一个字符。要获得更完整的解决方案,您需要构建一个no_linebreak(current, next)函数,该函数将整个lb表计入帐户,以确定两个字符之间是否存在换行符。

答案 1 :(得分:2)

快速解决方案(希望如此),而不是深入研究代码点语义(否则最好看看Martin的答案)。基于输出:

s = 'महाभूकम्पले'
for c in s:
    print(c, unicodedata.category(c))

这是:

म Lo
ह Lo
ा Mc
भ Lo
ू Mn
क Lo
म Lo
् Mn
प Lo
ल Lo
े Mn

我们可以使用前面的代码点加入这些类别( Mc Mn )中的代码点:

import unicodedata
from functools import reduce

def reducer(r, v):
    if unicodedata.category(v) in ('Mc', 'Mn'):
        r[-1] = r[-1] + v
    else:
        r.append(v)
    return r

print(reduce(reducer, 'महाभूकम्पले', []))

输出对应于gedit中的组合字符数:

['म', 'हा', 'भू', 'क', 'म्', 'प', 'ले']