8

我正在尝试解析 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为 acollections.deque和 use popleft(),反向argvusingreverse()和 use pop(),或者只是使用 int 列表索引本身。

有谁知道更好的方法来做到这一点,否则我的哪个想法在 Python 中是最佳实践?

4

6 回答 6

7

你可以做

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 程序中的选项和参数的标准,尽管对于这个任务来说它可能是多余的,因为你已经有了几个完美的功能解决方案。

于 2010-05-14T03:39:37.477 回答
7

另一个标准库模块: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'])
于 2010-05-14T07:09:58.253 回答
7

通过导入 sys,然后将 sys.argv[1:] 分配给变量,例如“args”,可以在 Bourne/Bash 中获得与“shift”等效的 Python 功能。然后您可以使用 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
于 2014-04-14T09:45:55.983 回答
3

就像是:

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

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

于 2010-05-14T03:45:01.910 回答
2

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

于 2010-05-14T04:23:05.377 回答
1

在 pythondel sys.argv[1]中执行shiftbash. 在 pythonsys.argv中是一个列表。删除索引上的元素与中1相同。shiftbash

下面的示例 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]
于 2018-03-13T14:48:55.183 回答