名前付き引数をシェルスクリプトに渡す


114

名前付きパラメーターをシェルスクリプトに渡す(受け取る)簡単な方法はありますか?

例えば、

my_script -p_out '/some/path' -arg_1 '5'

そして内部でmy_script.shそれらを受け取ります:

# I believe this notation does not work, but is there anything close to it?
p_out=$ARGUMENTS['p_out']
arg1=$ARGUMENTS['arg_1']

printf "The Argument p_out is %s" "$p_out"
printf "The Argument arg_1 is %s" "$arg1"

これはBashまたはZshで可能ですか?


2
見ていdocoptを -それは名前付きパラメータに役立ちますし、入力の検証は、あまりにん
ビート

回答:


34

それにおそらく最も近い構文は次のとおりです。

p_out='/some/path' arg_1='5' my_script

7
これに関連して、呼び出しシェル-kでオプションが設定されている場合、同じ効果があります。(コマンドの前の割り当てだけでなく、割り当ての形式のすべての引数が環境に追加されます。)my_script p_out='/some/path' arg_1='5'
chepner

13
以前はこの構文が大好きでしたが、大きな警告があります。コマンド/関数の実行後、これらの変数は現在のスコープでまだ定義されています!例:x=42 echo $x; echo $xこれは、の次の実行でmy_scriptp_out省略された場合、前回渡された値に固執することを意味します!! ('/some/path'
ルーカスシモン

@LucasCimon unset最初の実行後、次の実行前にリセットできませんか?
ニコスアレクサン

2
@LucasCimonそれは正しくありません。前に定義されていなかったx=42 echo $x場合、何も出力しません$x
ホークレイジング

あなたは正しいです@HaukeLaging、それを修正してくれてありがとう
ルーカスサイモン

148

あなたはすなわち、単一文字の引数名に限定されるものでは気にしない場合はmy_script -p '/some/path' -a5、その後、bashで、あなたはビルトイン使用することができgetopts、例えば

#!/bin/bash

while getopts ":a:p:" opt; do
  case $opt in
    a) arg_1="$OPTARG"
    ;;
    p) p_out="$OPTARG"
    ;;
    \?) echo "Invalid option -$OPTARG" >&2
    ;;
  esac
done

printf "Argument p_out is %s\n" "$p_out"
printf "Argument arg_1 is %s\n" "$arg_1"

その後、あなたはできる

$ ./my_script -p '/some/path' -a5
Argument p_out is /some/path
Argument arg_1 is 5

役立つSmall getoptsチュートリアルがあるhelp getopts、シェルプロンプトで入力できます。


25
これが受け入れ答えなければなりません
KaushikによるGhose

3
私はこれが少し古いことを知っていますが、なぜ議論のために1文字だけですか?
ケビン

1
これを実装しました(ただし、id)。で実行するとmy_script -i asd -d asdd引数に空の文字列を取得します。実行するmy_script -d asd -i asdと、両方の引数に空の文字列が取得されます。
Milkncookiez

3
@Milkncookiez-同様の問題がありました-最後の引数の後に ':'を含めませんでした(私の場合は 'w')。私は追加すると「:」それが期待どおりに動作し始めた
デレク

37

drupal.orgからこれを盗みましたが、次のようなことができます:

while [ $# -gt 0 ]; do
  case "$1" in
    --p_out=*)
      p_out="${1#*=}"
      ;;
    --arg_1=*)
      arg_1="${1#*=}"
      ;;
    *)
      printf "***************************\n"
      printf "* Error: Invalid argument.*\n"
      printf "***************************\n"
      exit 1
  esac
  shift
done

唯一の注意点は、構文を使用する必要があるということですmy_script --p_out=/some/path --arg_1=5


7
警告は必要ありません。:)次のように条件を設定できます-c|--condition)
。– Milkncookiez

28

私はこのスクリプトを使用し、魅力のように機能します。

for ARGUMENT in "$@"
do

    KEY=$(echo $ARGUMENT | cut -f1 -d=)
    VALUE=$(echo $ARGUMENT | cut -f2 -d=)   

    case "$KEY" in
            STEPS)              STEPS=${VALUE} ;;
            REPOSITORY_NAME)    REPOSITORY_NAME=${VALUE} ;;     
            *)   
    esac    


done

echo "STEPS = $STEPS"
echo "REPOSITORY_NAME = $REPOSITORY_NAME"

使用法

bash my_scripts.sh  STEPS="ABC" REPOSITORY_NAME="stackexchange"

コンソール結果:

STEPS = ABC
REPOSITORY_NAME = stackexchange

STEPSおよびREPOSITORY_NAMEはスクリプトで使用する準備ができています。

引数の順序は関係ありません。


4
これはきちんとしていて、受け入れられた答えであるはずです。
ミゲルモリン

15

ではzsh、次を使用しますzparseopts

#! /bin/zsh -
zmodload zsh/zutil
zparseopts -A ARGUMENTS -p_out: -arg_1:

p_out=$ARGUMENTS[--p_out]
arg1=$ARGUMENTS[--arg_1]

printf 'Argument p_out is "%s"\n' "$p_out"
printf 'Argument arg_1 is "%s"\n' "$arg_1"

ただし、スクリプトはで呼び出しますmyscript --p_out foo

zparseopts長いオプションや--p_out=fooGNUのような構文の省略をサポートしていないことに注意してくださいgetopt(3)


zparseoptsが引数にダッシュを1つだけ使用しているのに対し、[]ダッシュでは2 つのダッシュを使用している理由を知っていますか?意味を成さない!
ティモ

@Timo、詳細info zsh zparseoptsはこちら
ステファンシャゼル

9

このスクリプトを思いついたばかりです

while [ $# -gt 0 ]; do

   if [[ $1 == *"--"* ]]; then
        v="${1/--/}"
        declare $v="$2"
   fi

  shift
done

のように渡しmy_script --p_out /some/path --arg_1 5、スクリプトで$arg_1and を使用できます$p_out


私はしなければならなかったKSH88でこのソリューションが好きですv=``echo ${1} | awk '{print substr($1,3)}'`` typeset $v="$2"(各側に1つのバックティックを削除します)
hol

-2

関数またはアプリケーションに0個以上の引数がある場合、常に最後の引数があります。

次のようにオプションフラグと値のペアを読み取りたい場合: $ ./t.sh -o output -i input -l last

そして、オプション/値のペアの可変数を受け入れたい、

そして、巨大な「if .. then .. else .. fi」ツリーは必要ありません。

次に、ゼロ以外の偶数の引数カウントをチェックした後、

これらの4つのevalステートメントを本文としてwhileループを記述し、その後、ループの各パスで決定された2つの値を使用するcaseステートメントを記述します。

スクリプトの扱いにくい部分を以下に示します。

#!/bin/sh    

# For each pair - this chunk is hard coded for the last pair.
eval TMP="'$'$#"
eval "PICK=$TMP"
eval TMP="'$'$(($#-1))"
eval "OPT=$TMP"

# process as required - usually a case statement on $OPT
echo "$OPT \n $PICK"

# Then decrement the indices (as in third eval statement) 

:<< EoF_test
$ ./t.sh -o output -i input -l last
-l 
last
$ ./t.sh -o output -l last
-l 
last
$ ./t.sh  -l last
-l 
last
EoF_test

-3
mitsos@redhat24$ my_script "a=1;b=mitsos;c=karamitsos"
#!/bin/sh
eval "$1"

スクリプトスコープ内にコマンドラインパラメーターを挿入しました。


3
これは、OPが指定した構文では機能しません。彼らが欲しい-a 1 -b mitsos -c karamitsos
マイケルMrozek
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.