![getopts中没有指定选项时执行默认选项](https://linux22.com/image/8187/getopts%E4%B8%AD%E6%B2%A1%E6%9C%89%E6%8C%87%E5%AE%9A%E9%80%89%E9%A1%B9%E6%97%B6%E6%89%A7%E8%A1%8C%E9%BB%98%E8%AE%A4%E9%80%89%E9%A1%B9.png)
我按照教程进行操作这里学习如何使用getopts
。我能够执行用户正确提供的所有选项。但现在我想在没有提供任何选项时执行默认选项。
例如:
while getopts ":hr" opt; do
case $opt in
h )
show_help;
exit 1
;;
r )
echo "Default option executed"
;;
esac
done
因此,如果用户提供 或-h
,-r
则应执行相应的命令(实际上确实如此),但如果未提供这些选项,-r
则应默认执行。有办法实现这一点吗?
更新
我尝试了cas's
建议并将其纳入*)
我的getopts
功能中,但似乎没有发生任何事情。
while getopts ":hr" opt; do
case $opt in
h )
show_help;
exit 1
;;
r )
echo "Default option executed"
;;
\? )
echo error "Invalid option: -$OPTARG" >&2
exit 1
;;
: )
echo error "Option -$OPTARG requires an argument."
exit 1
;;
* )
echo "Default option executed"
;;
esac
done
这段代码有什么问题吗?
答案1
向语句添加默认选项不会有帮助,因为如果没有要解析的选项,case
则不会执行该语句。getopts
您可以看到它使用 shell 变量处理了多少个选项OPTIND
。从help getopts
:
Each time it is invoked, getopts will place the next option in the
shell variable $name, initializing name if it does not exist, and
the index of the next argument to be processed into the shell
variable OPTIND. OPTIND is initialized to 1 each time the shell or
a shell script is invoked.
因此,如果OPTIND
为 1,则不处理任何选项。在循环后添加以下内容while
:
if (( $OPTIND == 1 )); then
echo "Default option"
fi
答案2
while
当没有提供选项时,Bash 的 getopts 将退出循环,将 $opt 设置为“?”。要确定脚本中的这种情况,请在循环if
后添加一个子句while
,类似于:
if [ "$opt" = "?" ]
then
echo "Default option executed (by default)"
fi
作为参考,请参阅Bourne Shell 内置函数
答案3
使用getopts
循环根据传递的参数设置变量。然后对这些变量采取行动:
#!/bin/sh
# Defaults:
do_help=0
do_r=0
while getopts "hr" opt; do
case $opt in
h) do_help=1 ;;
r) do_r=1 ;;
*) echo 'Error in command line parsing' >&2
exit 1
esac
done
if [ "$do_help" -eq 1 ]; then
show_help
exit
fi
printf 'Default option executed (r=%d)\n' "$do_r"
我选择让代码在-h
使用时成功退出(除非show_help
失败),而不是使用非零退出状态(寻求帮助不是错误)。
运行它:
$ sh script.sh -r
Default option executed (r=1)
$ sh script.sh
Default option executed (r=0)
$ sh script.sh -h
script.sh[24]: show_help: not found
这样做的好处是将命令行解析代码与脚本的其余逻辑分开。
它还允许您在循环后进行基本的健全性检查,同时保持实际的解析循环简短。例如:
# command line parsing loop above here
if [ "$do_help" -eq 1 ] && [ "$do_r" -eq 1 ]; then
echo 'Options -h and -r are mutually exclusive' >&2
exit 1
fi
# code that acts on user-supplied options below
答案4
据我所知, r 并不期待争论。从逻辑上讲,无论发生什么,r 都会以相同的方式执行。
我会将与 r 相关的命令从 getopts 子句中取出并让它执行。我相信这足以满足您的要求。换句话说,将 echo 语句放在“done”语句之后。
如果您希望出于兼容性或其他原因,可以将 r 作为存根保留在 getopts 中。
您还可以添加设置为零的变量作为开关。一旦选择了 r 以外的任何选项,就会有一行将该变量更改为 1。在完成语句之后,您可以编写“如果变量等于 0,则执行默认命令”。
我想我最喜欢Cas的回答。我想发表评论,但我没有特权。我会以他的想法为基础。这与 Cas 提出的相同,但你只有一个命令(所以你不会有两个相同的命令并在将来犯错误),并且它会给你除了 - 之外还使用它的可能性H。
DEF="Default command executed"
while getopts ":hr" opt;
do case $opt in
h) show_help;
exit 1 ;;
r) echo "$DEF" ;;
*) echo "$DEF" ;;
esac
done