我想解析一个字符串字段中的列表,该字符串字段可能包含特殊字符,例如\ \ 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";
你对此有什么建议吗?
答案 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']