BASH 在脚本中同时使用位置参数和可选参数

BASH using both positional and optional arguments in a script

我目前正在编写一个 BASH 脚本,我想在其中使用位置参数和可选参数。位置参数必须出现在指定的位置(例如:$1、$2),而可选参数可以出现在它们的命令行标志指示的任何位置。这是我的脚本:

#!/usr/bin/env bash

usage() {
cat << EOF
Usage: progam ACTION NAME -k KEY_NAME
    ACTION ...... The program action to initiate
    NAME ........ The name of the object to create
    KEY_NAME .... The key name to use
EOF
}

ACTION=
NAME=
KEY_NAME=""

while getopts "k:" opt; do
    case $opt in
        k) KEY_NAME=$OPTARG; ;;
        [?]) usage && exit 1;
    esac
done

if [[ ! $ACTION ]]; then
    echo "Please select an action."
    exit 1
fi

if [[ ! $NAME ]]; then
    echo "Please include a name for the object."
    exit 1
fi

if [[ "$KEY_NAME" != "" ]]; then
    python3 -m program $ACTION -k $KEY_NAME -n $NAME
else
    echo "Please include a key name."
    exit 1
fi

exit 0

到 运行 我希望能够执行以下操作的程序:

fun_bash [action] [name] -k [key_name]

其中括号中的内容将被实际字符串替换。我执行的时候总是命中键名不存在的条件:

Please include a key name.

如何在同一脚本中包含强制性位置参数和可选命令行标志?

您可以在当前脚本中使用 变通方法

#!/usr/bin/env bash    
usage() {
cat << EOF
Usage: progam ACTION NAME -k KEY_NAME
    ACTION ...... The program action to initiate
    NAME ........ The name of the object to create
    KEY_NAME .... The key name to use
EOF
}

action=""
name=""
shift 2

key_name=""    
while getopts "k:" opt || :; do
    case $opt in
        k) key_name=$OPTARG; break ;;
        [?]) shift;;
    esac
done    
if [[ -z $action ]]; then
    echo "Please select an action."
    exit 1
fi    
if [[ -z $name ]]; then
    echo "Please include a name for the object."
    exit 1
fi    
if [[ -n $key_name ]]; then
    python3 -m program $action -k $key_name -n $name
else
    echo "Please include a key name."
    exit 1
fi    

主要区别在于在 while 循环之前使用 shift 2,因为前 2 个参数是固定的,所以将参数移动 2 个位置。

还要注意 getopts 循环中 [?]) shift;; 的使用,它会在每次不满足已知选项时移动参数,即 -k.

另请注意,您应避免在脚本中使用所有大写变量名称,以免覆盖内置 shell 变量。

通过这些更改,接受以下所有命令行:

fun_bash arg1 arg2 -k mykey
fun_bash arg1 arg2 arg3 arg4 -k mykey
fun_bash arg1 arg2 arg3 arg4 arg5 -k mykey