我正在尝试建立一个接受各种选项的shell脚本,这getopts
似乎是一个不错的解决方案,因为它可以处理选项和参数的变量顺序(我认为!)。
我只使用简短选项,每个简短选项都需要一个相应的值,例如::./command.sh -a arga -g argg -b argb
但我希望允许以非特定顺序输入选项,因为大多数人习惯于使用Shell命令。
另一点是,我希望对case
语句参数值进行自己的检查,最好是在语句中进行检查。原因是我:)
在case
陈述中对的测试产生了不一致的结果(可能是由于缺乏理解)。
例如:
#!/bin/bash
OPTIND=1 # Reset if getopts used previously
if (($# == 0)); then
echo "Usage"
exit 2
fi
while getopts ":h:u:p:d:" opt; do
case "$opt" in
h)
MYSQL_HOST=$OPTARG
;;
u)
MYSQL_USER=$OPTARG
;;
p)
MYSQL_PASS=$OPTARG
;;
d)
BACKUP_DIR=$OPTARG
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 2;;
:)
echo "Option -$OPTARG requires an argument" >&2
exit 2;;
esac
done
shift $((OPTIND-1))
echo "MYSQL_HOST='$MYSQL_HOST' MYSQL_USER='$MYSQL_USER' MYSQL_PASS='$MYSQL_PASS' BACKUP_DIR='$BACKUP_DIR' Additionals: $@"
发生这种情况而失败... ./command.sh -d -h
当我希望它将-d标记为需要参数时,但得到的值-d=-h
不是我所需要的。
因此,我认为在case语句中运行自己的验证会更容易,以确保每个选项都只设置一次。
我正在尝试执行以下操作,但未if [ ! "$MYSQL_HOST" ]; then
触发我的代码块。
OPTIND=1 # Reset if getopts used previously
if (($# == 0)); then
echo "Usage"
exit 2
fi
while getopts ":h:u:p:d:" opt; do
case "$opt" in
h)
MYSQL_HOST=$OPTARG
if [ ! "$MYSQL_HOST" ]; then
echo "host not set"
exit 2
fi
;;
u)
MYSQL_USER=$OPTARG
if [ ! "$MYSQL_USER" ]; then
echo "username not set"
exit 2
fi
;;
p)
MYSQL_PASS=$OPTARG
if [ ! "$MYSQL_PASS" ]; then
echo "password not set"
exit 2
fi
;;
d)
BACKUP_DIR=$OPTARG
if [ ! "$BACKUP_DIR" ]; then
echo "backup dir not set"
exit 2
fi
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 2;;
#:)
# echo "Option -$opt requires an argument" >&2
# exit 2;;
esac
done
shift $((OPTIND-1))
echo "MYSQL_HOST='$MYSQL_HOST' MYSQL_USER='$MYSQL_USER' MYSQL_PASS='$MYSQL_PASS' BACKUP_DIR='$BACKUP_DIR' Additionals: $@"
是否有原因我无法检查内部是否OPTARG
具有零长度getopts ... while ... case
?
有什么更好的方式来与经营自己的参数验证getopts
的情况下,我不希望被依靠:)
。在while ... case ... esac
?之外执行我的参数验证。
然后,我可能最终得到-d
etc的参数值,而没有捕获到丢失的选项。
while
在选项上运行了一个循环这一事实,便说得通。这是我使用的方法,尽管与其他方法相比比较冗长,但很清楚脚本中正在发生什么。在这种情况下,其他人的可维护性很重要。