getopts
我正在使用通过名为 的变量使用的惯用方式arg
。我可以捕获选项名称,如下所示。是否可以检测 getopts 到达“--”的时刻,以便我可以发出消息?
while getopts "$shortopts" arg; do
echo "--> arg: $arg"
case $arg in
("V")
printf '%s\n' "Version"
return
;;
("u")
printf '%s\n' "Usage"
return
;;
("h")
printf '%s\n' "Help"
return
;;
esac
done
答案1
是否可以检测 getopts 到达“--”的时刻,以便我可以发出消息?
你不应该需要这样做。
getopts
实现标准选项处理,这意味着当它看到不是选项的参数时,或者如果它看到参数 时,它会停止寻找选项--
,这会显式终止选项列表。 (第一点与 GNU 自定义不同,GNU 自定义在整个命令行上查找选项。)
程序不需要关心 meet --
。
也就是说,由于getopts
不会丢弃位置参数列表,因此您可以查看其中最后一个参数是否为--
.
#!/bin/bash
while getopts a:bc opt; do
echo "option $opt arg $OPTARG"
done
last=
if [ "$OPTIND" -ge 2 ]; then
shift "$((OPTIND - 2))"
last=$1
shift 1
else
shift "$((OPTIND - 1))"
fi
if [ "$last" = "--" ]; then
echo "options were terminated by a double-dash (or last arg was an option-argument '--')"
fi
echo "remaining args: $*"
那会给例如
$ bash opts.sh -a blah -- -b foo
option a arg blah
options were terminated by a double-dash (or last arg was an option-argument '--')
remaining args: -b foo
但由于它只查看最后一个参数,因此它可以是--
分隔符,也可以--
作为某个选项的选项参数。例如,这是误报,--
这里不是分隔符:
$ bash opts.sh -a -- foo
option a arg --
options were terminated by a double-dash (or last arg was an option-argument '--')
remaining args: foo
当然,您也可以实现自己的选项处理,但是这样做有点烦人,因为 shell 使处理子字符串变得很困难。 (您需要将其识别-abc
为三个不同的选项,或者一个或两个,具体取决于是否-a
或-b
采用选项参数。)
无论如何,除非您正在做的事情比通常需要的复杂得多,否则没有任何理由考虑--
.即使您做了更复杂的事情,您也可能会考虑在外部(并使用另一个分隔符)进行操作,类似于如何给出getopts
in 表达式,或者 GNU Parallel 如何获取由 分隔的参数列表等。find
:::
::::
答案2
循环后,getopts
习惯做:
shift "$((OPTIND - 1))"
剩下的参数将是剩下的。 (参见man getopts
1POSIX 的示例 1 部分)。
重点是,来自描述:
以下任何情况都应标识选项的结尾:第一个“--”参数不是选项参数,找到不是选项参数且不以“-”开头的参数,或者遇到错误。
假设你有pattern ab:
,那么(这里是4.示范--
):
-a x y z
-a
旗帜。休息:x y z
-a -b foo x y z
-a
标志 +-b
值 =foo
.休息:x y z
-b foo -a -b bar x y z
-a
标志 +-b
值 =foo
和bar
.休息:x y z
- 的两个值均已
-b
传递。取决于脚本如何处理。
-a -b foo -- -a -b x y z
-a
标志 +-b
值 =foo
.休息:-a -b x y z
-a -b foo -x y z
- 错误/未知选项
-x
- 错误/未知选项
-b foo bar -x y z
-b
值 =foo
.休息:bar -x y z
-b -- -a bar -x y z
-a
标志 +-b
值 =--
.休息:bar -x y z
至于 7,请注意,作为选项的参数可以有任何字符串,包括--
, 或""
。
$((...))
1 但请注意该示例如何缺少;周围的引号。 POSIX 示例确实假设$IFS
包含其默认值,这是不幸的,因为它们不能在任何上下文中使用。
答案3
将getopts
循环条件设置为初始化为 0 的变量,在这种"--")
情况下将其设置为 1。例如
stop=0
...
while [[ 0 -eq $stop ]] ; do
# getopts call ...
...
"--") stop=1;;r
esac
done