2012-04-28 110 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章。