我有一个 shell 脚本,它接受 4 个输入选项 (x:m:b:v)。但我想限制我的输入选项。
条件1
1. Accept option x or x and b
eg: sh script -x <arg> (or) ;will execute function a defined in script
sh script -x <arg> -b ;will execute the functions a and b
条件2
2. Accept option m or m and b
eg: sh script -m <arg> (or) ;execute function c
sh script -m <arg1> -b ;should execute function for c and b
条件3
3. Option both x and m should not be passed together.
This will print usage(how to use the input options) function.
条件4
4. Option v. This should not be passed with any other option.
eg: sh script -v <arg> ; executs the function for v
我知道这可以通过 if 和 else 条件来实现,但我无法获得条件的逻辑。
此外,如果没有传递任何输入参数(或者)传递了所有输入参数,它应该执行使用函数。
答案1
作为说明我上面的评论的一个例子,这里是 FreeBSD 的摘录/usr/src/bin/cp/cp.c
:
while ((ch = getopt(argc, argv, "HLPRafilnprsvx")) != -1)
switch (ch) {
case 'H':
Hflag = 1;
Lflag = 0;
break;
case 'L':
Lflag = 1;
Hflag = 0;
break;
...
case 'l':
lflag = 1;
break;
...
case 's':
sflag = 1;
break;
case 'v':
vflag = 1;
break;
case 'x':
fts_options |= FTS_XDEV;
break;
default:
usage();
break;
}
请注意,上面设置了很多布尔变量,如 Hflag、Lflag、lflag、sflag 等。这不仅允许代码测试标志之间的布尔关系,而且还允许一个标志的存在来激活另一个标志,或覆盖其他。另请注意,当用户指定未定义的选项标志时,default
该语句的子句switch
会强制调用。usage()
至于标志排除,例如不允许mflag
&& xflag
,类似的情况出现在 cp.c 中:
if (lflag && sflag)
errx(1, "the -l and -s options may not be specified together");
以下是该代码从 C 语言的可能翻译,bash
并对您的示例进行了额外的调整:
flagb=
flagm=
flagv=
flagx=
while getopts "bm:vx:" ch
do
case "$ch" in
[bv])
eval flag$ch=1
printf 'flag%s set\n' "$ch"
;;
[mx])
eval flag$ch=1
eval arg$ch=\"$OPTARG\"
printf 'flag%s set\n' "$ch"
printf 'arg%s is "%s"\n' "$ch" "$OPTARG"
;;
-)
break
;;
esac
done
[[ $OPTIND > 1 ]] && shift $(($OPTIND-1))
if [[ "$flagv" ]]
then
if [[ -n "$flagb$flagm$flagx" ]]
then
printf 'error: -v cannot be used with any other flags\n' >&2
exit 2
fi
fi
if [[ "$flagm$flagx" = "11" ]]
then
printf 'error: -m and -x cannot be used together\n' >&2
exit 2
fi
if [[ "$flagb" ]] && ! [[ "$flagm$flagx" ]]
then
printf 'error: -b requires either -m or -x\n' >&2
exit 2
fi
[[ "$flagb" ]] && printf 'b flag is set\n'
[[ "$flagm" ]] && printf 'm flag is set, arg is "%s"\n' "$argm"
[[ "$flagv" ]] && printf 'v flag is set\n'
[[ "$flagx" ]] && printf 'x flag is set, arg is "%s"\n' "$argx"
[[ "$@" ]] && {
printf 'remaining arguments:'
printf ' "%s"' "$@"
printf '\n'
}