Bash Shell Script-Проверьте флаг и возьмите его значение


Я пытаюсь сделать скрипт, который предназначен для запуска такой:

script.sh -t application

во-первых, в моем скрипте я хочу проверить, если скрипт был запущен с флагом-t. Например, если он был запущен без флага, как это я хочу, чтобы ошибка:

script.sh

во-вторых, предполагая, что есть флаг - t, я хочу захватить значение и сохранить его в переменной, которую я могу использовать в своем скрипте, например, так:

FLAG="application"

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

4 54

4 ответа:

вы должны прочитать эту 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, недостаточно аргументов:

if [ $# -ne 2 ]; then
   usage;
fi

далее проверить, если равна -t, в противном случае использовался неизвестный флаг:

if [ "" != "-t" ]; then
  usage;
fi

наконец-магазине на FLAG:

FLAG=

Примечание: usage() это какая-то функция, показывающая синтаксис. Например:

function usage {
   cat << EOF
Usage: script.sh -t <application>

Performs some activity
EOF
   exit 1
}

вот обобщенный простой интерфейс аргумента команды, который вы можете вставить в верхнюю часть всех ваших сценариев.

#!/bin/bash

declare -A flags
declare -A booleans
args=()

while [ "" ];
do
    arg=
    if [ "${1:0:1}" == "-" ]
    then
      shift
      rev=$(echo "$arg" | rev)
      if [ -z "" ] || [ "${1:0:1}" == "-" ] || [ "${rev:0:1}" == ":" ]
      then
        bool=$(echo ${arg:1} | sed s/://g)
        booleans[$bool]=true
        echo \"$bool\" is boolean
      else
        value=
        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 arguemnt разбора снова!

попробуйте shFlags -- Расширенная библиотека флагов командной строки для сценариев оболочки Unix.

http://code.google.com/p/shflags/

Это очень хорошо и очень гибкий.

типы флагов: это список DEFINE_*'s, что вы можете сделать. Все флаги берем имя, значение по умолчанию, строка справки и необязательное "короткое" имя (однобуквенное имя.) Некоторые флаги имеют другие аргументы, которые описываются с флагом.

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: принимает входной сигнал и бесстрашно его как число с плавающей запятой. Как оболочка не поддерживает поплавки per-se, вход просто проверяется как будучи допустимым значением с плавающей точкой.

DEFINE_integer: принимает входные данные и интерпретирует их как целое число.

специальные флаги: есть несколько флагов, которые имеют особое значение: -- помогите (или -?) печатает список всех флагов в удобочитаемом виде -- flagfile=foo читать флаги из foo. (пока не реализовано ) -- как в getopt (), завершается флаг-обработка

ПРИМЕР ИСПОЛЬЗОВАНИЯ:

-- begin hello.sh --
 ! /bin/sh
. ./shflags
DEFINE_string name 'world' "somebody's name" n
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
echo "Hello, ${FLAGS_name}."
-- end hello.sh --

$ ./hello.sh -n Kate
Hello, Kate.

Примечание: я взял этот текст из документации shflags