web-dev-qa-db-ja.com

Bashシェルスクリプト-フラグを確認し、その値を取得します

次のように実行されるように設計されたシェルスクリプトを作成しようとしています。

script.sh -t application

まず、スクリプトで-tフラグを指定してスクリプトが実行されたかどうかを確認します。たとえば、このようなフラグなしで実行された場合、エラーが発生します:

script.sh

次に、-tフラグがあると仮定して、値を取得し、スクリプトで使用できる変数に保存します。たとえば、次のようになります。

FLAG="application"

これまでのところ、私がこれまでに達成できた唯一の進歩は、$ @がすべてのコマンドライン引数を取得することですが、これがフラグとどのように関連するか、またはこれが可能かどうかはわかりません。

62
Jimmy

これを読む必要があります 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

Greybotが言ったように(getopt!= getopts):

外部コマンドgetopt(1)は決して安全ではありません。あなたがknowGNU getoptでない限り、 GNU固有の方法、andGETOPT_COMPATIBLEが環境にないことを確認します。代わりにgetopts(シェル組み込み)を使用するか、単に位置パラメーターをループします。

100
Gilles Quenot

$#を使用して引数の数を取得します。2に等しくない場合、十分な引数が提供されません。

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

次に、$1-tと等しいかどうかを確認します。等しくない場合は、不明なフラグが使用されました。

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

最後に$2FLAGに保存します:

FLAG=$2

注:usage()は、構文を示す関数です。例えば:

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

Performs some activity
EOF
   exit 1
}
24
Veger

これは、すべてのスクリプトの先頭に貼り付けることができる一般化された単純なコマンド引数インターフェイスです。

#!/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引数の解析に対処することを許可します!

更新されたスクリプトを表示できます ここ

これは、この1年で非常に役立ちました。変数の前にスコープパラメーターを付けることで、スコープをシミュレートできるようになりました。

次のようにスクリプトを呼び出すだけです

replace() (
  source $FUTIL_REL_DIR/commandParser.sh -scope ${FUNCNAME[0]} "[email protected]"
  echo ${replaceFlags[f]}
  echo ${replaceBooleans[b]}
)

引数スコープを実装したようには見えませんが、なぜそれがまだ必要ではないのかわかりません。

9

ShFlagsを試してください-Unixシェルスクリプト用の高度なコマンドラインフラグライブラリ。

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

非常に優れており、非常に柔軟です。

フラグの種類:これは、DEFINE_ *のリストです。すべてのフラグは、名前、デフォルト値、ヘルプ文字列、およびオプションの「短い」名前(1文字の名前)を取ります。一部のフラグには他の引数があり、フラグとともに説明されています。

DEFINE_string:入力を受け取り、文字列として解釈します。

DEFINE_boolean:通常、引数を取りません。たとえば、-myflagでFLAGS_myflagをtrueに設定するか、-nomyflagでFLAGS_myflagをfalseに設定します。または、--myflag = trueまたは--myflag = tまたは--myflag = 0または--myflag = falseまたは--myflag = fまたは--myflag = 1と指定することもできます。オプションを渡すと、一度オプション。

DEFINE_float:入力を受け取り、浮動小数点数として解釈します。シェルはそれ自体フロートをサポートしていないため、入力は有効な浮動小数点値として検証されるだけです。

DEFINE_integer:入力を受け取り、整数として解釈します。

特別なフラグ:特別な意味を持つフラグがいくつかあります:--help(または-?)は、人間が読める形式ですべてのフラグのリストを出力します--flagfile = foo fooからフラグを読み取ります。 (まだ実装されていません)-getopt()のように、フラグ処理を終了します

使用例:

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

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

注:このテキストはshflagsのドキュメントから取得しました

0
Anandkumar