在Python中以前缀表示法处理命令行参数

时间:2010-05-14 02:57:36

标签: python data-structures stack command-line-arguments prefix

我正在尝试用Python解析命令行,如下所示:

$ ./command -o option1 arg1 -o option2 arg2 arg3

换句话说,该命令接受无限数量的参数,并且每个参数可以选择性地以-o选项开头,该选项与该参数具体相关。我认为这被称为“前缀表示法”。

在Bourne shell中,我会做类似以下的事情:

while test -n "$1"
do
    if test "$1" = '-o'
    then
        option="$2"
        shift 2
    fi
    # Work with $1 (the argument) and $option (the option)
    # ...
    shift
done

环顾Bash教程等,这似乎是公认的习惯用法,所以我猜测Bash已经过优化,可以通过这种方式使用命令行参数。

尝试在Python中实现这种模式,我的第一个猜测是使用pop(),因为这基本上是一个堆栈操作。但是我猜这在Python上不会有效,因为sys.argv中的参数列表顺序错误,必须像队列一样处理(即从左侧弹出)。我已经读过,列表没有优化用作Python中的队列。

所以,我的想法是:将argv转换为collections.deque并使用popleft(),使用argv转换reverse()并使用pop(),或者可能只是使用int list索引本身。

有没有人知道更好的方法来做到这一点,否则我的哪些想法在Python中是最好的做法?

6 个答案:

答案 0 :(得分:6)

另一个stdlib模块:argparse

p = argparse.ArgumentParser()
p.add_argument('-o', action='append')
for i in range(1, 4): p.add_argument('arg%d' % i)
args = p.parse_args('-o option1 arg1 -o option2 arg2 arg3'.split())
print args
# -> Namespace(arg1='arg1', arg2='arg2', arg3='arg3', o=['option1', 'option2'])

答案 1 :(得分:5)

你可以做到

argv.pop(0)

拉出第一个元素并返回它。但这可能效率低下。也许。我不确定argv是如何在幕后实施的。 (再说一次,如果效率 重要,为什么要使用Python?)

但是,更加Pythonic的解决方案是迭代列表而不会弹出元素。像这样:

o_flag = False
for a in argv:
    if a == '-o':
        o_flag = True
        continue
    # do whatever
    o_flag = False

另外,我认为optparse模块值得一提;它是处理Python程序中的选项和参数的标准,尽管它可能对此任务有点过分,因为您已经有了几个功能完善的解决方案。

答案 2 :(得分:5)

Python功能等同于" shift"在Bourne / Bash中可以通过导入sys,然后将sys.argv [1:]分配给变量,例如, " ARGS&#34 ;.然后你可以使用args = args [1:]向左移动一次,或使用更高的数字移动多次。参数索引将从0开始,而不是1.上面的示例看起来像:

import sys
args = sys.argv[1:]
while len(args):
    if args[0] == '-o':
        option = args[1]
        args = args[2:] # shift 2
    # Work with args[0] (the argument) and option (the option)
    # ...
    args = args[1:] # shift

答案 3 :(得分:2)

类似的东西:

for arg in sys.argv[1:]:
  # do something with arg

应该适合你。除非你期望有大量的参数,否则我会选择最简单的代码(并且不要过于担心性能)。 argv [1:]忽略了第一个argv值,它将是脚本的名称。

答案 4 :(得分:2)

无需重新发明轮子:getopt模块就是为此而设计的。如果这不符合您的需求,请尝试optparse模块,该模块更灵活但更复杂。

答案 5 :(得分:0)

在python中del sys.argv[1]执行与shift中的bash相同的操作。在python中sys.argv是一个列表。删除索引1上的元素与shift中的bash相同。

下面的示例python脚本将有助于跳过参数中的-o并考虑所有其他参数。

#!/usr/bin/python
import sys

if __name__ == '__main__':
    while len(sys.argv) > 1:
        if sys.argv[1] != "-o":
            print sys.argv[1]
        del sys.argv[1]