Bash Shell Script - Проверить флаг и получить его значение
Я пытаюсь создать оболочку script, которая предназначена для запуска следующим образом:
script.sh -t application
Во-первых, в моем script я хочу проверить, был ли script запущен с флагом -t. Например, если он был запущен без этого флага, я хочу, чтобы он был ошибкой:
script.sh
Во-вторых, если предположить, что существует флаг -t, я хочу захватить значение и сохранить его в переменной, которую я могу использовать в своем script, например, следующим образом:
FLAG="application"
До сих пор единственный прогресс, который я смог сделать в этом, заключается в том, что [email protected]захватывает все аргументы командной строки, но я не знаю, как это относится к флагам, или если это даже возможно.
Ответы
Ответ 1
Вы должны прочитать этот урок getopts.
Пример с переключателем -a
который требует аргумента:
#!/bin/bash
while getopts ":a:" opt; do
case $opt in
a)
echo "-a was triggered, Parameter: $OPTARG" >&2
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
Как сказал грейбот (getopt
! = getopts
):
Внешнюю команду getopt (1) никогда нельзя использовать безопасно, если только вы не знаете, что это GNU getopt, вы вызываете ее специфичным для GNU способом и убедитесь, что GETOPT_COMPATIBLE отсутствует в среде. Вместо этого используйте getopts (встроенную оболочку) или просто переключайтесь между позиционными параметрами.
Ответ 2
Используйте $#
, чтобы захватить количество аргументов, если оно не соответствует 2, недостаточно аргументов:
if [ $# -ne 2 ]; then
usage;
fi
Затем проверьте, соответствует ли $1
-t
, иначе использовался неизвестный флаг:
if [ "$1" != "-t" ]; then
usage;
fi
Наконец, сохраните $2
в FLAG
:
FLAG=$2
Примечание: usage()
- это некоторая функция, показывающая синтаксис. Например:
function usage {
cat << EOF
Usage: script.sh -t <application>
Performs some activity
EOF
exit 1
}
Ответ 3
Вот обобщенный простой интерфейс аргументов команды, который вы можете вставить в начало всех ваших скриптов.
#!/bin/bash
declare -A flags
declare -A booleans
args=()
while [ "$1" ];
do
arg=$1
if [ "${1:0:1}" == "-" ]
then
shift
rev=$(echo "$arg" | rev)
if [ -z "$1" ] || [ "${1:0:1}" == "-" ] || [ "${rev:0:1}" == ":" ]
then
bool=$(echo ${arg:1} | sed s/://g)
booleans[$bool]=true
echo \"$bool\" is boolean
else
value=$1
flags[${arg:1}]=$value
shift
echo \"$arg\" is flag with value \"$value\"
fi
else
args+=("$arg")
shift
echo \"$arg\" is an arg
fi
done
echo -e "\n"
echo booleans: ${booleans[@]}
echo flags: ${flags[@]}
echo args: ${args[@]}
echo -e "\nBoolean types:\n\tPrecedes Flag(pf): ${booleans[pf]}\n\tFinal Arg(f): ${booleans[f]}\n\tColon Terminated(Ct): ${booleans[Ct]}\n\tNot Mentioned(nm): ${boolean[nm]}"
echo -e "\nFlag: myFlag => ${flags["myFlag"]}"
echo -e "\nArgs: one: ${args[0]}, two: ${args[1]}, three: ${args[2]}"
Запустив команду:
bashScript.sh firstArg -pf -myFlag "my flag value" secondArg -Ct: thirdArg -f
Выход будет таким:
"firstArg" is an arg
"pf" is boolean
"-myFlag" is flag with value "my flag value"
"secondArg" is an arg
"Ct" is boolean
"thirdArg" is an arg
"f" is boolean
booleans: true true true
flags: my flag value
args: firstArg secondArg thirdArg
Boolean types:
Precedes Flag(pf): true
Final Arg(f): true
Colon Terminated(Ct): true
Not Mentioned(nm):
Flag: myFlag => my flag value
Args: one => firstArg, two => secondArg, three => thirdArg
В основном, аргументы делятся на логические флаги и общие аргументы. Делая это таким образом, пользователь может устанавливать флаги и логические значения в любом месте, пока он/она сохраняет общие аргументы (если они есть) в указанном порядке.
Позвольте мне и теперь вам больше никогда не иметь дело с разбором аргументов bash!
Вы можете просмотреть обновленный скрипт здесь
Это было чрезвычайно полезно за последний год. Теперь он может имитировать область видимости, добавляя переменные к параметру области видимости.
Просто назовите сценарий как
replace() (
source $FUTIL_REL_DIR/commandParser.sh -scope ${FUNCNAME[0]} "[email protected]"
echo ${replaceFlags[f]}
echo ${replaceBooleans[b]}
)
Не похоже, что я реализовал область действия аргумента, не уверен, почему, я думаю, он мне пока не нужен.
Ответ 4
Попробуйте shFlags - Расширенная библиотека флагов командной строки для сценариев оболочки Unix.
http://code.google.com/p/shflags/
Это очень хорошо и очень гибко.
FLAG TYPES: Это список DEFINE_ *, который вы можете сделать. Все флаги имя, значение по умолчанию, справочную строку и необязательное "короткое" имя (однобуквенное имя). Некоторые флаги имеют другие аргументы, которые описываются с помощью флага.
DEFINE_string: принимает любой ввод и интрепретирует его как строку.
DEFINE_boolean: обычно не принимает никаких аргументов: say --myflag для установки FLAGS_myflag - true, или --nomyflag, чтобы установить FLAGS_myflag в false. В качестве альтернативы вы можете сказать --myflag = true или --myflag = t или --myflag = 0 или --myflag = false или --myflag = f или --myflag = 1 Передача параметра имеет тот же эффект, что и переход опции.
DEFINE_float: принимает ввод и интрепретирует его как число с плавающей запятой. В виде shell не поддерживает поплавки per se, вход просто проверяется как является допустимым значением с плавающей запятой.
DEFINE_integer: принимает ввод и интрепретирует его как целое число.
СПЕЦИАЛЬНЫЕ ФЛАГИ: Есть несколько флагов, которые имеют особое значение: --help (или -?) печатает список всех флагов в удобном для восприятия человеком способом --flagfile = foo читать флаги из foo. (еще не реализовано) - как в getopt(), завершает обработку флага
ПРИМЕР ИСПОЛЬЗОВАНИЯ:
-- begin hello.sh --
! /bin/sh
. ./shflags
DEFINE_string name 'world' "somebody name" n
FLAGS "[email protected]" || exit $?
eval set -- "${FLAGS_ARGV}"
echo "Hello, ${FLAGS_name}."
-- end hello.sh --
$ ./hello.sh -n Kate
Hello, Kate.
Примечание. Я взял этот текст из документации shflags