2012-04-28 228 views
1

我正在用python寫一個CLI應用程序,通過一種相當複雜的命令行語言來使用。這個想法與找到(1)非常相似,可以說它具有相同的屬性。Python:解析命令行

目前,解析器是使用手工EBNF描述語言完全手寫的。問題是這種語言使用起來非常尷尬,因爲我必須將所有東西都寫成python結構。我也覺得我的程序由於解析而仍然過於臃腫。

是否有任何使用易用的lib,以及用於命令行解析的真正描述語言(輸入爲字符串/文檔)?從語法樹中,我想直接將每個項目映射到一個類實例。當然,我不想要標記器,或者至少標記器必須從命令行參數直接映射到標記。

感謝您的所有建議!

UPDATE:我的程序的全部要點是生成對象,並通過任何數量的過濾器(可能unpure/effectful動作)通過他們可能會或可能不會輸出再次對象,或另一甚至可能會輸出對象類型。從find(1)中顯然可以看出總體思路。一個命令行示例如下:

~/picdb.py -sqlselect 'select * from pics where dirname like "testdir%"' -tagged JoSo -updateFromFile [ -resx +300 -or -resX +200 -resY +500 ] -printfXml '<jpegfile><src>%fp</src><DateTimeOriginal>%ed</DateTimeOriginal><Manufacturer>%eM</Manufacturer><Model>%em</Model></jpegfile>%NL' 
+2

[argparse](http://docs.python.org/library/argparse.html#module-argparse)(python 2.7+)會滿足您的需求嗎? – Aufwind 2012-04-28 14:00:57

+0

除了@Aufwind的評論 - 你不需要*擁有python 2.7或更新的用戶argparse。它適用於老版本的python - 你只需要自己安裝(而不是被包含在標準庫中)。 – mgilson 2012-04-28 15:52:31

+0

我認爲,如果你描述了你的命令行(或者至少給出了一個或兩個例子),我們可能會看到這是否是一個候選人/ optparse ... – mgilson 2012-04-28 15:53:41

回答

3

這是一個非常棘手的問題......你可以很容易地使用argparse「綁定」動作到命令行參數(例如,創建一個類,在先前創建的類上操作......)。這是一個愚蠢的例子...(參數 - foo創建一個對象,參數--bar修改由--foo創建的對象)。

from argparse import ArgumentParser,Action 

class Foo(object): 
    def __init__(self,*args): 
     self.args=args 
    def __str__(self): 
     return str(self.args) 

class FooAction(Action): 
    def __call__(self,parser,namespace,values,option_string=None): 
     setattr(namespace,self.dest,Foo(*values)) #Add Foo to the options... 
class BarAction(Action): 
    def __call__(self,parser,namespace,values,option_string=None): 
     FooObj=getattr(namespace,'foo') #raises an error if foo isn't in namespace... 
             #In this way, BarAction is like a filter on the 
             #object created by foo. 
     FooObj.args=tuple(list(FooObj.args)+list(values)) #append to the list of args. 

parser=ArgumentParser() 
parser.add_argument('--foo',nargs='*',action=FooAction,help="Foo!") 
parser.add_argument('--bar',nargs='*',action=BarAction,help="Bar! : Must be used after --foo") 

namespace=parser.parse_args("--foo Hello World --bar Nice Day".split()) 
print (namespace) 
print (namespace.foo) 

然而,這是從你的一點點不同之處在於僅-argument是不是真的有可能與argparse,-a--argument。這可能已經是你的一個交易斷路器,我不確定...

下一個難題是處理括號... []。如果你可以把它們作爲不同命令行選項的參數,那麼你可能會好的......你可能可以設置第二個解析器來解析出內部部分 - 但我從來沒有嘗試過這樣的事情。 (如果其他人對如何處理括號有任何想法,我會非常感興趣的聽到他們)。

optparsegetopt而言,我非常肯定你可以用它們做任何事情,你可以用argparse來做,這就是爲什麼我讓他們離開討論的原因。

+0

非常感謝你的努力。這意味着我可能會留下我的手工解決方案。 – 2012-04-29 11:36:51

1

至少有三個模塊可以嘗試;​​,optparse(2.7中已棄用)和getopt。請參閱Python標準庫手冊的第15章。