问题描述
我想以 ./script speed -a some_value -b some_value
和 ./script accuracy -a some_value -b some_value
的身份运行脚本
我尝试的是
while [ -n "$1" ]; do
case "$1" in
speed)
for i in "${@:2}"
do while getopts "a:b:" opt; do
case "${opt}" in
a) list=$OPTARG
echo $list
;;
b) list2=$OPTARG
echo $list2
;;
esac
done
done
echo "speed option passed"
break ;;
accuracy) echo "similar to above function"
break ;;
*) echo "Option $1 not recognized" ;; # In case you typed a different option other than a,b,c
esac
shift
done
获得运行./script speed -a some_value
时的输出
this is something
speed option passed
我不知道这是否可行,或者有没有办法做这样的事情?
解决方法
我认为您不需要外循环 (while [ -n "$1" ]; do
),除非您希望能够在一次运行中处理多个子命令。也就是说,你想要这个:
./script speed -a some_value -b some_value accuracy -a some_value -b some_value
大致相当于:
./script speed -a some_value -b some_value
./script accuracy -a some_value -b some_value
如果不是,请删除该循环,因为每次运行您将只处理一个子命令。如果您确实希望每次运行处理多个子命令,那么在运行下一个子命令之前,您需要采取一些额外的步骤来删除或跳过与一个子命令相关的参数。
您确实想要删除 for i in "${@:2}"
循环——这与 getopts
的工作方式不符。您需要做的是在处理选项之前跳过子命令名称。您可以使用 shift
删除子命令名称,如下所示:
case "$1" in
speed)
shift # Remove the first argument ("speed")
while getopts "a:b:" opt; do
...
如果您要允许多个子命令,请在 shift $((OPTIND-1))
循环后添加 getopts
,以便为下一个子命令做好准备。
或者您可以修改 OPTIND
以告诉 getopts
它已经处理了第一个参数并且可以继续处理第二个参数:
case "$1" in
speed)
OPTIND=2 # Tell getopts to start processing at arg #2
while getopts "a:b:" opt; do
...
如果你打算用这种方法处理多个子命令......好吧,它有点复杂,我想我会回避这个问题。
另一种选择是将每个子命令的代码放在一个函数中,并使用除第一个参数之外的所有参数调用它:
speed_subcommand() {
local OPTIND
while getopts "a:b:" opt; do
...
}
case "$1" in
speed)
speed_subcommand "${@:2}" ;;
accuracy)
accuracy_subcommand "${@:2}" ;;
...
这种方法并没有真正与每次运行处理多个子命令混合在一起。