Подтвердить что ты не робот

Правильный способ проверить флаг командной строки в bash

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

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

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

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

4b9b3361

Ответ 1

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

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

Смотрите также BashFAQ/035.

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

Ответ 2

Я обычно вижу, как это делается с помощью заявления случая. Вот выдержка из скрипта 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 переменной.

Ответ 3

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

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

Getopt

Это автономный исполняемый файл, который существует уже давно. В старых версиях отсутствует способность обрабатывать аргументы в кавычках (например, "это не сработает") и версии, которые могут это делать, неуклюже. Если вы используете последнюю версию Linux, ваш "getopt" может сделать это; SCO 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

Ответ 4

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

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

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

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

if has_param '-t' "[email protected]"; 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 в конце командной строки (не говоря -h о том, хорош он или нет).


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

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

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