OptionParser - поддержка любого параметра в конце командной строки
Я пишу небольшую программу, которая должна выполнять команду на удаленном сервере (скажем, довольно глупая оболочка вокруг ssh [hostname] [command]
).
Я хочу выполнить это так:
./floep [команда]
Тем не менее, мне нужно время от времени передавать определенные командные строки:
./floep -v [команда]
поэтому я решил использовать optparse.OptionParser для этого. Проблема в том, что иногда у команды также есть аргумент, который отлично работает, если я это сделаю:
./floep -v "uname -a"
Но я также хочу, чтобы это работало, когда я использую:
./floep -v uname -a
Идея состоит в том, что, как только я столкнусь с первым аргументом без опций, все, что после этого должно стать частью моей команды.
Это, однако, дает мне:
Использование: floep [варианты] floep: error: нет такой опции: -a
OptionParser поддерживает этот синтаксис? Если так: как? Если нет: как лучше это исправить?
4 ответа
Попробуйте использовать disable_interspersed_args()
#!/usr/bin/env python
from optparse import OptionParser
parser = OptionParser()
parser.disable_interspersed_args()
parser.add_option("-v", action="store_true", dest="verbose")
(options, args) = parser.parse_args()
print "Options: %s args: %s" % (options, args)
Когда запустить:
$./options.py foo -v bar Опции: {'verbose': None} args: ['foo', '-v', 'bar'] $ ./options.py -v foo bar Опции: {'verbose': True} args: ['foo', 'bar'] $ ./options.py foo -a bar Опции: {'verbose': None} args: ['foo', '-a', 'bar']
Экземплярами OptionParser фактически можно манипулировать во время операции синтаксического анализа для сложных случаев. В этом случае, однако, я полагаю, что сценарий, который вы описываете, поддерживается "из коробки" (что было бы хорошей новостью, если это правда! Как часто это происходит??). Смотрите этот раздел в документации: Запросы и манипулирование вашим опциональным парсером.
Цитировать ссылку выше:
disable_interspersed_args ()
Установить разбор для остановки на первый не вариант. Используйте это, если у вас есть командный процессор, который запускает другую команду, которая имеет свои собственные параметры, и вы хотите, чтобы эти параметры не запутались. Например, у каждой команды может быть свой набор параметров.
from optparse import OptionParser
import subprocess
import os
import sys
parser = OptionParser()
parser.add_option("-q", "--quiet",
action="store_true", dest="quiet", default=False,
help="don't print output")
parser.add_option("-s", "--signal",
action="store_true", dest="signal", default=False,
help="signal end of program and return code")
parser.disable_interspersed_args()
(options, command) = parser.parse_args()
if not command:
parser.print_help()
sys.exit(1)
if options.quiet:
ret = subprocess.call(command, stdout=open(os.devnull, 'w'),
stderr=subprocess.STDOUT)
else:
ret = subprocess.call(command)
if options.signal:
print "END OF PROGRAM!!! Code: %d" % ret
Вы можете использовать скрипт bash следующим образом:
#!/bin/bash
while [ "-" == "${1:0:1}" ] ; do
if [ "-v" == "${1}" ] ; then
# do something
echo "-v"
elif [ "-s" == "${1}" ] ; then
# do something
echo "-s"
fi
shift
done
${@}
$ {@} Возвращает остальную часть командной строки, которая не была использована вызовами смены. Чтобы использовать ssh, просто измените строку с $ {@} на ssh $ {user} @ $ {host} $ {@}
test.sh echo bla
бла
test.sh -v echo bla
-v
бла
test.sh -v -s echo bla
-v
-s
бла