
Я работаю над скриптом bash и мне нужно реализовать "options". Как это сделать с помощью bash?
Моя цель — запустить скрипт следующим образом:
/myscript.sh -d "/var/log/" -c "test"
что я пробовал:
while shift; do
case $1 in
-d)
shift&&DIR="$1"||die
;;
-c)
shift&&COMMAND="$1"||die
;;
esac
done
echo "$DIR"
echo "$COMMAND"
решение1
Чтобы расширить ответ @choroba, вот пример того, как использовать getopts
:
# parse the flag options (and their arguments)
while getopts c:d: OPT; do
case "$OPT" in
d)
DIR="$OPTARG" ;;
c)
COMMAND="$OPTARG" ;;
[?])
# got invalid option
echo "Usage: $0 [-d directory] [-c command]" >&2
exit 1 ;;
esac
done
# get rid of the just-finished flag arguments
shift $(($OPTIND-1))
Обратите внимание, что после сдвига аргументов флага все "обычные" аргументы останутся. Так что в этот момент вы можете либо разобраться с ними (например, ... for arg in "$@"; do ...
), либо, если ваш скрипт их не принимает, просто пожаловаться, если они у вас есть ( if [ $# -gt 0 ]; then echo "Usage ...
).
решение2
Ваша ошибка в том, что вы смещаетесь в верхней части цикла, отбрасывая первый аргумент до того, как вы его рассмотрели. Вот что, я думаю, вы, вероятно, имели в виду:
#!/bin/bash
while (( "$#" )); do
case $1 in
-d)
shift&&DIR="$1"||die
;;
-c)
shift&&COMMAND="$1"||die
;;
esac
shift
done
echo "$DIR"
echo "$COMMAND"
решение3
Как уже сказал Чороба,getoptsэто лучший подход.
В вашем случае вы могли бы использовать:
getopts c:d: d || die
DIR=$OPTARG
getopts c:d: c || die
COMMAND=$OPTARG
чтобы добиться того, чего вы пытаетесь добиться с помощью цикла while.
Строка c:d:
указывает возможные переключатели. Двоеточие означает, что для переключателя требуется аргумент.
Проблема вашего подхода в том, что вы вызываете shift
до анализа первого аргумента, отбрасывая его в процессе.
Чтобы исправить это, измените цикл while следующим образом:
while true; do
case $1 in
-d)
shift&&DIR="$1"||die
;;
-c)
shift&&COMMAND="$1"||die
;;
esac
shift || break
done
решение4
Обычный подход — использовать getopts
.