我将这个 bash 代码与 getopts 结合起来,如果我正确理解了 getopts,OPTIND 包含下一个命令行选项的索引,并且提供给 shell 脚本的所有命令行选项都显示在变量 $1、$2、$3 等中。如果是,请纠正我我错了,但与函数中的局部变量的概念基本上相同。
所以根据这个为什么选项 [-a somevalue ]
不会[-b somevalue ]
给我任何结果。我究竟做错了什么?
OPT_A=A
OPT_B=B
while getopts :a:b FLAG; do
case $FLAG in
a)
OPT_A=$OPTARG
;;
b)
OPT_B=$OPTARG
;;
esac
done
shift $((OPTIND-1))
while [ $# -ne 0 ]; do
if [[ -z $OPT_A ]]; then
if [ `echo $1 | grep -o '\.' | wc -l` -ne 3 ]; then
echo "Parameter '$1' does not look like an IP Address (does not contain 3 dots).";
exit 1;
elif [ `echo $1 | tr '.' ' ' | wc -w` -ne 4 ]; then
echo "Parameter '$1' does not look like an IP Address (does not contain 4 octets).";
exit 1;
else
for OCTET in `echo $1 | tr '.' ' '`; do
if ! [[ $OCTET =~ ^[0-9]+$ ]]; then
echo "Parameter '$1' does not look like in IP Address (octet '$OCTET' is not numeric).";
exit 1;
elif [[ $OCTET -lt 0 || $OCTET -gt 255 ]]; then
echo "Parameter '$1' does not look like in IP Address (octet '$OCTET' in not in range 0-255).";
exit 1;
fi
done
fi
fi
if [[ -z $OPT_B ]]; then
if [[ "$2" =~ ^[0-9]+$ ]] && [ "$2" -ge 1 -a "$2" -le 10000 ]; then
echo "chosen variable: $2";
exit 1;
else echo "variable $2 is not in range '1 - 10000'";
exit 1;
fi
fi
done
exit 0
答案1
这是因为你的所有逻辑都依赖于其中之一$OPT_[AB]
为空。但即使您不传递参数-[ab] $OPTARG
,您仍然可以使用OPT_[AB]=[AB]
.所以你的逻辑链永远不会越过根源......
if [[ -z $OPT_A ]]; then...
...陈述。
嗯……不是全部你的逻辑取决于此。你也在做:
shift $((OPTIND-1))
while [ $# -ne 0 ]...
所以如果你通过了,script -a arg
那么getopts
就会设置$OPT_A
为arg
3。$OPTIND
所以你会shift 2
(你所有的职位)然后立即通过测试失败while
。所以你case
会设定$OPT_A
,接下来发生的事情是exit 0
。所以我猜你永远也不会去检查$OPT_A
是否有空的。
即使这样也没关系,因为你的大部分逻辑都是为了测试失败而设计的 - 但你的脚本仅有的 exit
s。你可能做了$OPT_A
var,但你没有用它做任何事情。你不能在 script 后使用该值exit
- 没有一些预设的 IPC,但这里没有这些。该脚本在子 shell 中调用,并且当它返回到父 shell 时,它设置的值将丢失。
更重要的是 optstring:a:b
不允许$OPTARG
to -b
。 optstring 中的前导冒号表示安静操作 -stderr
如果选项或其参数存在问题,它不会写入。但是一个冒号尾随选项字符表示该选项应该有一个参数。喜欢:
while getopts :a:b: FLAG
...这将表明两个需要参数的选项。但这可能很棘手,因为如果您指示它应该接受一个参数,那么如果getopts
发现它没有参数,则会将其标记为错误:
sh -c 'getopts :a:b: opt -a; echo "$opt $OPTARG"'
...打印...
: a
在这种情况下,期权最终结果为$OPTARG
,:
最终结果为$opt
。如果我们:
对此不那么沉默的话就会更清楚:
sh -c 'getopts a:b: opt -a; echo "$opt $OPTARG"'
No arg for -a option
因此,您需要检查:
冒号和?
- 这是另一种类型的错误,通常会重新路由以打印一些简短的--help
内容。
就我个人而言,我会确保$OPT_[AB]
一开始都是空的,执行一些逻辑来正确设置它们,并且在完成测试循环后,将我的最后一个测试设置为空值。如果它们根本没有任何价值,那么它一定是由于某种我没有处理的原因,无论如何它都是一个错误。这是我将如何进行测试循环的开始......
param_err(){
set '' "$@"
: "${1:?Parameter '$OPTARG' does not look like an IP Address $2}"
}
test_oct(){
oIFS=$IFS; unset "${IFS+o}oIFS"; IFS=.
for oct in $1; do [ $oct -lt 256 ] ||
param_err "('$oct' too large)"
done; unset IFS oct
: "${oIFS+${IFS=$oIFS}}"
}
a_param()
case ${1##*.*.*.*.*} in (a) OPT_A=A;; #some default - no arg provided
(.*|*..*|*.) param_err '(empty octet)';;
(*[!.0-9]*) param_err '(octet is not positive integer)';;
(*.*.*.*) test_oct "$1"; OPT_A=$1;;
(*?*) param_err '(too few octets)';;
(*) param_err ${1:+"(too many octets)"} '(null param)';;
esac
unset OPT_A OPT_B
while getopts :a:b:c:d: opt
do case ${opt#:}$OPTARG in
a*) a_param "$OPTARG";;
b*) b_param "$OPTARG";; #tests as needed similar to a_param()
?*) help;; #param_err should call this too, but it just exits
esac
done
答案2
顶部没有 shebang 行,因此您使用的 shell ( sh
, dash
) 可能不支持[[
。您应该使用以下命令启动脚本:
#!/bin/bash
或任何其他位置bash
,在不太可能的情况下,这不是系统上 bash 的路径 ( type bash
)。
答案3
尝试更改此设置: while getopts :a:b FLAG;做
对此: while getopts :a:b: FLAG;做