在bash脚本中,我想从配置文件加载设置,并使用命令行选项覆盖各个设置.如果在配置文件和命令行中同时指定了设置,则命令行设置应优先.
如何确保在其他getopts块之前加载配置文件?这是我得到的:
#!/bin/bash
# ...
while getopts “c:l:o:b:dehruwx” OPTION
do
case $OPTION in
c)
echo "load"
CONFIG_FILE=$OPTARG
# load_config is a function that sources the config file
load_config $CONFIG_FILE
;;
l)
echo "set local"
LOCAL_WAR_FILE=$OPTARG
;;
# ...
esac
done
shift $(($OPTIND - 1))
Run Code Online (Sandbox Code Playgroud)
无论我为-c选项设置处理程序的顺序如何,它总是在设置其他选项之后加载配置文件.这使得将配置文件设置与命令行选项合并更加困难.
每次调用getopts总是处理"下一个"选项(由检查确定$OPTIND),因此您的while-loop必须按照它们出现的顺序处理选项.
由于您希望-c被其他选项部分取代,即使它出现在命令行之后,您也可以采取一些方法.
一种是将选项循环两次:
#!/bin/bash
# ...
optstring='c:l:o:b:dehruwx'
while getopts "$optstring" OPTION
do
case $OPTION in
c)
echo "load"
CONFIG_FILE=$OPTARG
# load_config is a function that sources the config file
load_config $CONFIG_FILE
esac
done
OPTIND=1
while getopts "$optstring" OPTION
do
case $OPTION in
l)
echo "set local"
LOCAL_WAR_FILE=$OPTARG
;;
# ...
esac
done
shift $(($OPTIND - 1))
Run Code Online (Sandbox Code Playgroud)
另一种方法是将选项保存在-c 不会覆盖的变量中,然后将它们复制到:
#!/bin/bash
# ...
while getopts c:l:o:b:dehruwx OPTION
do
case $OPTION in
c)
echo "load"
CONFIG_FILE=$OPTARG
# load_config is a function that sources the config file
load_config $CONFIG_FILE
;;
l)
echo "set local"
LOCAL_WAR_FILE_OVERRIDE=$OPTARG
;;
# ...
esac
done
shift $(($OPTIND - 1))
LOCAL_WAR_FILE="${LOCAL_WAR_FILE_OVERRIDE-${LOCAL_WAR_FILE}}"
Run Code Online (Sandbox Code Playgroud)
(或者,相反,配置文件可以设置类似的选项LOCAL_WAR_FILE_DEFAULT,然后你就可以了LOCAL_WAR_FILE="${LOCAL_WAR_FILE-${LOCAL_WAR_FILE_DEFAULT}}".)
另一种选择是要求-c,如果存在,首先.你可以先自己处理它:
if [[ "$1" = -c ]] ; then
echo "load"
CONFIG_FILE="$2"
# load_config is a function that sources the config file
load_config "$CONFIG_FILE"
shift 2
fi
Run Code Online (Sandbox Code Playgroud)
然后在你的主while循环中,只需-c通过打印错误消息来处理.
另一个是简单地记录您现有的行为并将其称为"功能".很多Unix实用程序后来的选项都取代了之前的选项,所以这种行为并不是真正的问题.