4

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

这就是我目前拥有的

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";

你对此有什么建议吗?

4

1 回答 1

2

正如您在此处显示的那样,Pyparsing 非常容忍空白字符,所以我很惊讶这是一个问题。

您确实遇到的一个问题是您的定义list_G

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

我明白你在这里想要做什么,但你的列表元素表达式有一个关键问题。delimitedList(expr)是一个方便的快捷方式expr + ZeroOrMore(Suppress(',') + expr),但您使用的列表元素表达式exprWord(printables),任何非空白字符的词组。不幸的是,这包括“,”,您的列表分隔符。当您将字符串 "one,two,three" 传递给此表达式时,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 版本中,我excludeChars在 Word 中添加了一个参数来简化这一点。现在你可以写:

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']
于 2012-12-07T08:44:32.917 回答