获取整个Unicode句子
我正在尝试解析一个句子,比如 Base: Lote Numero 1, Marcelo T de Alvear 500. Demanda: otras palabras.
我想做的是:首先,把文本按句号分开,然后,把冒号前面的部分当作后面句子的 标签
。
from pyparsing import *
unicode_printables = u''.join(unichr(c) for c in xrange(65536)
if not unichr(c).isspace())
def parse_test(text):
label = Word(alphas)+Suppress(':')
value = OneOrMore(Word(unicode_printables)|Literal(','))
group = Group(label.setResultsName('label')+value.setResultsName('value'))
exp = delimitedList(
group,
delim='.'
)
return exp.parseString(text)
现在我有了以下的定义:
这个方法有点效果,但它把一些特殊字符(还有那些不是字母或数字的东西)给去掉了。我希望能把 值
保留为完整的句子,而不是现在这样:'value': [(([u'Lote', u'Numero', u'1', ',', u'Marcelo', u'T', u'de', u'Alvear', u'500'], {}), 1)
。
有没有简单的方法来解决这个问题呢?
2 个回答
你可以看看 PyICU 这个工具,它可以让你使用ICU提供的强大Unicode文本库。里面有一个叫 BreakIterator 的类,可以帮助你找到句子。
直接回答你的问题,你可以用 originalTextFor
来包裹你的值定义,这样就能得到一个字符串片段,里面包含了匹配的标记来源,结果是一个完整的字符串。你也可以加一个解析动作,比如:
value.setParseAction(lambda t : ' '.join(t))
不过这样做会在每个项目之间加一个空格,而实际上可能没有空格(比如在一个单词后面跟着逗号的情况),或者有多个空格。使用 originalTextFor
可以得到你输入的确切子字符串。但如果你只是想读取 ':' 后面的所有内容,使用 restOfLine
会更简单。(当然,最简单的方式是直接用 split(':')
,但我猜你是特别想知道怎么用 pyparsing 来实现这个。)
还有几点补充:
xxx.setResultsName('yyy')
可以简化为xxx('yyy')
,这样能让你的解析器定义更易读。你定义的值为
OneOrMore(Word(unicode_printables) | Literal(','))
有几个问题。首先,逗号 ',' 会被包含在unicode_printables
的字符集中,所以解析出来的单词中也会包含逗号。解决这个问题的最好方法是使用Word
的excludeChars
参数,这样你的句子单词就不会包含逗号了:OneOrMore(Word(unicode_printables, excludeChars=',') | ',')
。现在你也可以通过在 excludeChars 字符串中添加其他可能的标点符号(比如 ';'、'-' 等)来排除它们。(我刚注意到你用 '.' 作为delimitedList
的分隔符——为了让这个工作,你也需要把 '.' 加入到排除的字符中。)在这方面,pyparsing 和普通的正则表达式不一样——它不会提前查看下一个标记是否匹配,如果下一个字符仍然匹配当前标记的话。因此,你需要自己做一些额外的工作,以避免读取过多。一般来说,像OneOrMore(Word(unicode_printables))
这样开放的定义,很可能会把你输入字符串的其余部分都吃掉。