![如何在 POSIX shell 中使用 getopts 检查传递的选项? (报告、计数并丢弃。)](https://linux22.com/image/221553/%E5%A6%82%E4%BD%95%E5%9C%A8%20POSIX%20shell%20%E4%B8%AD%E4%BD%BF%E7%94%A8%20getopts%20%E6%A3%80%E6%9F%A5%E4%BC%A0%E9%80%92%E7%9A%84%E9%80%89%E9%A1%B9%EF%BC%9F%20%EF%BC%88%E6%8A%A5%E5%91%8A%E3%80%81%E8%AE%A1%E6%95%B0%E5%B9%B6%E4%B8%A2%E5%BC%83%E3%80%82%EF%BC%89.png)
如何使用检查传递的选项getopts
(手册页)在 POSIX shell 中? (报告、计数并丢弃。)
我的想法是这样的:我的许多脚本不采用任何选项(甚至不是-h
为了帮助,我help
直接过渡到)。因此,如果给出任何数量的选项(开关),我想对它们进行计数,报告它们,然后简单地丢弃他们(不要对他们做任何操作)。
让我们包括所有0-9
, 以及下层和上层a-z
( A-Z
)。
更新:我的许多脚本甚至不接受文件作为参数,这个脚本就是这种情况。
用法帮助看起来像这样:
usage ()
{
cat << EOF
MPV video player subtitles enable/disable toggling
--------------------------------------------------
on Enable subtitles toggling in MPV.
off Disable subtitles toggling in MPV.
help Print this help message.
version Print the script version.
EOF
}
答案1
如果您的脚本不采用任何选项,但您想检查(错误地)传递了哪些选项并自行处理错误,则可以在getopts
选项规范:
中添加在$OPTARG
.引用getopts
实用程序的 POSIX 规范(强调我的):
如果选项字符不包含在可选字符串如果在需要选项字符的位置找到操作数,则名称指定的 shell 变量应设置为 <问号> (
?
) 字符。在这种情况下,如果第一个字符可选字符串是 <colon> (:
),shell 变量OPTARG
应设置为找到的选项字符,但不会将输出写入标准错误;否则,应取消设置 shell 变量OPTARG
,并将诊断消息写入标准错误。此情况应被视为在向调用应用程序提供参数的方式中检测到的错误,但不应是getopts
处理中的错误。
所以你可以这样写:
optnum=0; while getopts : opt; do
printf >&2 '%s\n' "Illegal option -$OPTARG"
optnum=$(( optnum + 1 ))
done
if [ "$optnum" -gt 0 ]; then
printf >&2 '%s\n' "Some ($optnum) option switches were passed to the script, but none expected!"
fi
shift "$(( OPTIND - 1 ))"
if [ "$#" -gt 0 ]; then
echo "Non-option argument${2+s}:"
printf ' - %s\n' "$@"
fi
例子:
$ ./that-script -asd --output=asd -- rest
Illegal option -a
Illegal option -s
Illegal option -d
Illegal option --
Illegal option -o
Illegal option -u
Illegal option -t
Illegal option -p
Illegal option -u
Illegal option -t
Illegal option -=
Illegal option -a
Illegal option -s
Illegal option -d
Some (14) option switches were passed to the script, but none expected!
Non-option argument:
- rest
但是不带任何选项(但仍处理 )的脚本--
通常只是:
PROGNAME=$0
usage() {
printf >&2 '%s\n' "Usage: $PROGNAME [<file> [<file>...]]"
exit 1
}
getopts '' opt && usage
shift "$(( OPTIND - 1))"
for file do
printf 'Got "%s"\n' "$file"
done
并且在出现第一个错误时仍然以失败退出状态退出,这是最明智的做法。
$ ./that-script -weirdly-named-.txt
./that-script: illegal option -- w
Usage: ./that-script [<file> [<file>...]]
$ ./that-script -- -weirdly-named-.txt
Got "-weirdly-named-.txt"
我们getopts
通过省略前缀来输出有关无效选项本身的错误消息:
。
当然,在选项处理之后,您可以根据需要验证其余参数。例如,如果您的脚本也不接受非选项参数,则在调用后shift
:
if [ "$#" -ne 0 ]; then
echo>&2 'This script does not accept any argument.'
usage
fi
实际上,它只能被称为that-script
or that-script --
。尽管您也可以跳过getopts
并拒绝任何参数,无论它们是选项、选项分隔符还是非选项参数。
或对于Usage: cmd [<type> <length> <value> [<type> <length> <value>]...]
:
if [ "$(( $# % 3 ))" -ne 0 ]; then
echo>&2 'The number of arguments must be a multiple of 3'
usage
fi
等等。