使用pyparsing从具有特殊字符的字符串中解析列表

时间:2012-12-06 22:45:56

标签: python pyparsing

我想解析一个字符串字段中的列表,该字符串字段可能包含特殊字符,例如\ \ n \ r \ n \ t \ n,并在多行上展开。目前,我必须首先解析字符串,清理它,然后在该干净的字符串上应用列表语法。它工作正常,但只是想知道是否有更好的方法。

这就是我目前所拥有的

str_ = QuotedString('"',escChar='\\',multiline=True)  #grammar for str
str_.setParseAction(lambda pr: pr[0].replace('\\n',' ')\
                        .replace('\\r', ' ')\
                        .replace('\r', ' ')\
                        .replace('\t', ' '))

list_G = delimitedList(Word(printables))('mlist') #grammar for list


def pa(st,locn,pr): return list_G.parseString(pr.mystr)
mylist = Group(str_('mystr').addParseAction(pa)) #read in the str then re-parse
G = Keyword("LIST") + mylist('thelist') + ';'    #grammar for the whole thing
s = 'LIST "one,two,three" ;'  

编辑: 而不是list_G中的Word(printables),改为

var_grammar = Word(alphas+"_", alphanums + "_") #"_a,a2b_,.."
num_grammar = Regex(r"[+-]?\d+(:?\.\d*)?(:?[eE][+-]?\d+)?")('num')
list_G = delimitedList(var_grammar|num_grammar)('mlist') #grammar for list
G = Keyword("LIST") + '"' + mylist('thelist') + '"' + ';' 

迫使我进行清理以替换"\\n", "\\r" with ' '的原因是因为我从字面上包含字符\n, \r的文件中读取字符串,并且这些文件不能由var_name或num解析(它们不可打印)

这是文件中(原始)字符串的示例:

LIST "one,two,
 three,
 \nfour,\rfive";

你对此有什么建议吗?

1 个答案:

答案 0 :(得分:1)

Pyparsing非常容忍你在这里展示的空白字符,所以我很惊讶这是一个问题。

的一个问题在于您对list_G的定义:

list_G = delimitedList(Word(printables))('mlist') #grammar for list

我得到你在这里要做的事情,但你的列表元素表达式有一个关键问题。 delimitedList(expr)expr + ZeroOrMore(Suppress(',') + expr)的便捷快捷方式,但您用于expr的列表元素表达式是Word(printables),是任何非空白字符的单词组。不幸的是,这包括',',您的列表分隔符。当您将字符串“1,2,3”传递给此表达式时,Word(printables)将在查找分隔符之前解析整个事物:

>>> list_G = delimitedList(Word(printables))
>>> print (list_G.parseString("one,two,three"))
['one,two,three']

你需要一种方式来说“我希望我的话能成为不是逗号的可打印的一切”。在较旧版本的pyparsing中,您必须自己使用以下内容执行此操作:

word_of_everything_except_a_comma = Word(''.join(c for c in printables if c != ','))

在1.5.6版本中,我向Word添加了一个excludeChars参数来简化此操作。现在你可以写:

word_of_everything_except_a_comma = Word(printables, excludeChars=',')

通过这样的单词,您将得到一个合适的3元素列表:

>>> list_G = delimitedList(Word(printables, excludeChars=','))
>>> print (list_G.parseString("one,two,three"))
['one', 'two', 'three']

这可能是你正在努力解决的问题,因为pyparsing将隐含地跳过你正在剥离的空白字符:

>>> s = "one,  two\t\t,\n\n\t\t\t  three"
>>> print (s)
one,  two               ,

                          three
>>> print (list_G.parseString(s))
['one', 'two', 'three']