我正在尝试构建一个接受各种选项的 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: $@"Run Code Online (Sandbox Code Playgroud)
像这样的事件失败了......./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: $@"Run Code Online (Sandbox Code Playgroud)
是否有原因我无法OPTARG从内部检查 a 是否具有零长度getopts ... while ... case?
有什么更好的方式来与经营自己的参数验证getopts的情况下,我不希望被依靠:)。在while ... case ... esac?之外执行我的参数验证
然后我可以得到-detc 的参数值,而不是捕捉到丢失的选项。
当您使用以下命令调用第二个脚本(我将其保存为getoptit)时:
getoptit -d -h
Run Code Online (Sandbox Code Playgroud)
这将打印:
MYSQL_HOST='' MYSQL_USER='' MYSQL_PASS='' BACKUP_DIR='-h' Additionals:
Run Code Online (Sandbox Code Playgroud)
所以 BACKUP_DIR 已设置,并且您正在测试if [ ! "$BACKUP_DIR" ]; then这样就设置了BACKUP_DIR,如果没有设置则
如果您想测试每个选项是否设置一次,则必须在根据 $OPTARG 值进行分配之前执行此操作。在分配之前,您可能还应该检查 $OPTARG 是否以 a 开头'-'(针对错误):-d -h
...
d)
if [ ! -z "$BACKUP_DIR" ]; then
echo "backup dir already set"
exit 2
fi
if [ z"${OPTARG:0:1}" == "z-" ]; then
echo "backup dir starts with option string"
exit 2
fi
BACKUP_DIR=$OPTARG
;;
...
Run Code Online (Sandbox Code Playgroud)