Python - pyparsing Unicode字符

14 投票
3 回答
7866 浏览
提问于 2025-04-15 19:45

:) 我试着用 w = Word(printables),但它没有成功。我应该怎么给这个参数呢?'w' 是用来处理印地语字符的(UTF-8格式)。

这段代码定义了语法,并根据这个语法进行解析。

671.assess  :: अहसास  ::2
x=number + "." + src + "::" + w + "::" + number + "." + number

如果只有英文字符,它是可以工作的,所以这段代码在ASCII格式下是正确的,但在Unicode格式下就不行了。

我的意思是,当我们有像这样的内容时:671.assess :: ahsaas ::2

也就是说,它可以解析英文格式的单词,但我不太确定如何解析并打印Unicode格式的字符。我需要这个来对齐英文和印地语单词。

这段Python代码看起来是这样的:

# -*- coding: utf-8 -*-
from pyparsing import Literal, Word, Optional, nums, alphas, ZeroOrMore, printables , Group , alphas8bit , 
# grammar 
src = Word(printables)
trans =  Word(printables)
number = Word(nums)
x=number + "." + src + "::" + trans + "::" + number + "." + number
#parsing for eng-dict
efiledata = open('b1aop_or_not_word.txt').read()
eresults = x.parseString(efiledata)
edict1 = {}
edict2 = {}
counter=0
xx=list()
for result in eresults:
  trans=""#translation string
  ew=""#english word
  xx=result[0]
  ew=xx[2]
  trans=xx[4]   
  edict1 = { ew:trans }
  edict2.update(edict1)
print len(edict2) #no of entries in the english dictionary
print "edict2 has been created"
print "english dictionary" , edict2 

#parsing for hin-dict
hfiledata = open('b1aop_or_not_word.txt').read()
hresults = x.scanString(hfiledata)
hdict1 = {}
hdict2 = {}
counter=0
for result in hresults:
  trans=""#translation string
  hw=""#hin word
  xx=result[0]  
  hw=xx[2]
  trans=xx[4]
  #print trans
  hdict1 = { trans:hw }
  hdict2.update(hdict1)

print len(hdict2) #no of entries in the hindi dictionary
print"hdict2 has been created"
print "hindi dictionary" , hdict2
'''
#######################################################################################################################

def translate(d, ow, hinlist):
   if ow in d.keys():#ow=old word d=dict
    print ow , "exists in the dictionary keys"
        transes = d[ow]
    transes = transes.split()
        print "possible transes for" , ow , " = ", transes
        for word in transes:
            if word in hinlist:
        print "trans for" , ow , " = ", word
                return word
        return None
   else:
        print ow , "absent"
        return None

f = open('bidir','w')
#lines = ["'\
#5# 10 # and better performance in business in turn benefits consumers .  # 0 0 0 0 0 0 0 0 0 0 \
#5# 11 # vHyaapaar mEmn bEhtr kaam upbhOkHtaaomn kE lIe laabhpHrdd hOtaa hAI .  # 0 0 0 0 0 0 0 0 0 0 0 \
#'"]
data=open('bi_full_2','rb').read()
lines = data.split('!@#$%')
loc=0
for line in lines:
    eng, hin = [subline.split(' # ')
                for subline in line.strip('\n').split('\n')]

    for transdict, source, dest in [(edict2, eng, hin),
                                    (hdict2, hin, eng)]:
        sourcethings = source[2].split()
        for word in source[1].split():
            tl = dest[1].split()
            otherword = translate(transdict, word, tl)
            loc = source[1].split().index(word)
            if otherword is not None:
                otherword = otherword.strip()
                print word, ' <-> ', otherword, 'meaning=good'
                if otherword in dest[1].split():
                    print word, ' <-> ', otherword, 'trans=good'
                    sourcethings[loc] = str(
                        dest[1].split().index(otherword) + 1)

        source[2] = ' '.join(sourcethings)

    eng = ' # '.join(eng)
    hin = ' # '.join(hin)
    f.write(eng+'\n'+hin+'\n\n\n')
f.close()
'''

如果源文件的示例输入句子是:

1# 5 # modern markets : confident consumers  # 0 0 0 0 0 
1# 6 # AddhUnIk baajaar : AshHvsHt upbhOkHtaa .  # 0 0 0 0 0 0 
!@#$%

输出将看起来像这样:

1# 5 # modern markets : confident consumers  # 1 2 3 4 5 
1# 6 # AddhUnIk baajaar : AshHvsHt upbhOkHtaa .  # 1 2 3 4 5 0 
!@#$%

输出解释:- 这实现了双向对齐。 这意味着英文的第一个单词 'modern' 对应印地语的第一个单词 'AddhUnIk',反之亦然。在这里,甚至字符也被视为单词,因为它们也是双向映射的重要部分。因此,如果你注意到印地语的单词 '.' 没有对应的对齐,因为它在英文句子中没有句号。 输出的第三行基本上表示一个分隔符,当我们处理多个句子时,用于实现双向映射。

如果我有Unicode(UTF-8格式)的印地语句子,我应该做什么修改才能让它工作?

3 个回答

1

我在查找法语的Unicode字符时,发现了这个问题。如果你想搜索法语或其他带有拉丁字母重音的字符,使用pyparsing 2.3.0的话,可以这样做:

>>> pp.pyparsing_unicode.Latin1.alphas
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzªµºÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ'
28

Pyparsing中的printables只处理ASCII字符范围内的字符串。你想要的是完整Unicode范围内的可打印字符,比如这样:

unicodePrintables = u''.join(unichr(c) for c in xrange(sys.maxunicode) 
                                        if not unichr(c).isspace())

现在你可以用这个更完整的非空格字符集合来定义trans

trans = Word(unicodePrintables)

我没能测试你的印地语测试字符串,但我觉得这样应该可以解决问题。

(如果你使用的是Python 3,那么就没有单独的unichr函数,也没有xrange生成器,只需使用:

unicodePrintables = ''.join(chr(c) for c in range(sys.maxunicode) 
                                        if not chr(c).isspace())

编辑:

随着pyparsing 2.3.0的最新发布,新的命名空间类被定义出来,以提供printablesalphasnumsalphanums,以适应各种Unicode语言范围。

import pyparsing as pp
pp.Word(pp.pyparsing_unicode.printables)
pp.Word(pp.pyparsing_unicode.Devanagari.printables)
pp.Word(pp.pyparsing_unicode.देवनागरी.printables)
8

一般来说,不要直接处理编码后的字节串。你应该尽快把它们转换成正确的Unicode字符串(通过调用它们的.decode方法),然后在处理时始终使用Unicode字符串。如果因为输入输出的需要,最后再把它们用.encode方法转换回你需要的字节串编码。

如果你在说字面量,就像你代码中那样,“尽快”就是立刻:使用u'...'来表示你的字面量。在更一般的情况下,如果你必须以编码形式进行输入输出,那就在输入后立即转换(如果你需要以特定编码形式进行输出,那就在输出前立即转换)。

撰写回答