Правильный способ проверить наличие флага командной строки в bash - PullRequest
35 голосов
/ 20 мая 2010

В середине скрипта я хочу проверить, был ли данный флаг передан в командной строке. Следующее делает то, что я хочу, но кажется безобразным:

if echo $* | grep -e "--flag" -q
then
  echo ">>>> Running with flag"
else
  echo ">>>> Running without flag"
fi

Есть ли лучший способ?

Примечание: Я явно не хочу перечислить все флаги в switch / getopt. (В этом случае любые такие вещи станут половиной или более от полного сценария. Также тела if просто устанавливают набор переменных)

Ответы [ 4 ]

54 голосов
/ 20 мая 2010

Альтернатива тому, что вы делаете:

if [[ $* == *--flag* ]]

См. Также BashFAQ / 035 .

Примечание : Это также будет соответствовать --flags-off, поскольку это простая проверка подстроки.

9 голосов
/ 20 мая 2010

Обычно я вижу, что это сделано с помощью case. Вот выдержка из скрипта git-repack :

while test $# != 0
do
    case "$1" in
    -n) no_update_info=t ;;
    -a) all_into_one=t ;;
    -A) all_into_one=t
        unpack_unreachable=--unpack-unreachable ;;
    -d) remove_redundant=t ;;
    -q) GIT_QUIET=t ;;
    -f) no_reuse=--no-reuse-object ;;
    -l) local=--local ;;
    --max-pack-size|--window|--window-memory|--depth)
        extra="$extra $1=$2"; shift ;;
    --) shift; break;;
    *)  usage ;;
    esac
    shift
done

Обратите внимание, что это позволяет проверять как короткие, так и длинные флаги. В этом случае другие параметры создаются с использованием переменной extra.

6 голосов
/ 20 мая 2010

Вы можете использовать ключевое слово getopt в bash.

С http://aplawrence.com/Unix/getopts.html:

Getopt

Это автономный исполняемый файл, который существует уже давно. В старых версиях отсутствует способность обрабатывать аргументы в кавычках (foo a "this не будет работать "в) и версии, которые могут, сделать это неуклюже. Если вы запустив последнюю версию Linux, ваш "getopt" может это сделать; ШОС OSR5, Mac OS X 10.2.6 и FreeBSD 4.4 имеют более старую версию, которая этого не делает.

Простое использование getopt показано в этом мини-скрипте:

#!/bin/bash
echo "Before getopt"
for i
do
  echo $i
done
args=`getopt abc:d $*`
set -- $args
echo "After getopt"
for i
do
  echo "-->$i"
done
0 голосов
/ 03 июня 2019

Вы можете воспользоваться простым подходом и перебрать аргументы, чтобы проверить каждый из них на равенство с заданным параметром (например, -t).

поместить его в функцию:

has_param() {
    local term="$1"
    shift
    for arg; do
        if [[ $arg == "$term" ]]; then
            return 0
        fi
    done
    return 1
}

… и используйте его как предикат в тестовых выражениях:

if has_param '-t' "$@"; then
    echo "yay!"
fi

if ! has_param '-t' "$1" "$2" "$wat"; then
    echo "nay..."
fi

, если вы хотите отклонить пустые аргументы, добавьте точку выхода вверху тела цикла:

for arg; do
    if [[ -z "$arg" ]]; then
        return 2
    fi
    # ...

это очень читабельно и не даст вам ложных срабатываний, как, например, сопоставление с образцом или сопоставление с регулярным выражением.
это также позволит размещать флаги в произвольных позициях, например, вы можете поставить -h в конце командной строки (не говоря уже о том, хорошо это или плохо).


но , чем больше я об этом думал, тем больше что-то беспокоило меня.

с помощью функции вы можете взять любую реализацию (например, getopts) и использовать ее повторно.инкапсуляция rulez!
но даже с командами эта сила может стать недостатком.если вы будете использовать его снова и снова, вы будете анализировать все аргументы каждый раз.

Моя тенденция состоит в том, чтобы поддерживать повторное использование, но я должен знать о последствиях.противоположный подход заключается в том, чтобы проанализировать эти аргументы один раз в начале скрипта, как вы и боялись, и избежать повторного анализа.
вы все равно можете инкапсулировать этот регистр переключателя, который может быть настолько большим, насколько вы решили (у вас нетк списку все опций).

...