Bash: Как использовать while shift; do..case $1 в

Bash: Как использовать while shift; do..case $1 в

Я работаю над скриптом 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.

Связанный контент