У меня есть скрипт оболочки, который принимает 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'
}