2012-12-06 80 views
3

我想從可能包含特殊字符(如\\ n \ r \ n \ t)的字符串字段中解析列表,並在多行中展開。目前,我必須首先解析字符串,將其清理乾淨,然後將清單語法應用於該清理字符串。它工作正常,但只是想知道是否有更好的方法。使用pyparsing從特殊字符的字符串中解析列表

這是我目前有

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

編輯: 相反字(printables)在list_G的,改爲

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

您可以編輯您的問題,包括在's'一些特殊字符,並顯示問題是什麼,如果你沒有在這兩個步驟的方式解析? – PaulMcG

+0

如果實際上字符串本身具有反斜槓和'n'字符,則定義一個表達式,如'unwanted = Word('\\','rnt',exact = 2)',然後執行'G .IGNORE(不想要的)'。 – PaulMcG

+0

這似乎是一個很好的解決方案 - 應該等同於當前我的黑客攻擊,在讀入文件之後並解析之前,用空格替換那些「\ t \ n \ r」。謝謝 –

回答

1

Pyparsing對你在這裏顯示的空白字符非常寬容,所以我很驚訝這是一個問題。

一個問題,你有在你的list_G定義:

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

我明白你想在這裏做什麼,而是你的列表元素表達式有一個關鍵問題。 delimitedList(expr)expr + ZeroOrMore(Suppress(',') + expr)的簡便快捷方式,但您用於expr的列表元素表達式是Word(printables),它是任何非空白字符的一個詞組。不幸的是,這包括',',你的列表分隔符。當你通過字符串「一,二,三」這個表達,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_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'] 
+0

嗨保羅,我使用變量和數字的語法,但決定使用'printables'的帖子,因爲它更乾淨(見編輯後)。我編輯了我的原創貼子,當事情不起作用時,我有一個例子。希望你可以看看。 –