コマンドライン引数をBashの配列に変換する


160

コマンドライン引数をbashスクリプト配列に変換するにはどうすればよいですか?

私はこれを取りたい:

./something.sh arg1 arg2 arg3

そしてそれを

myArray=( arg1 arg2 arg3 )

スクリプトでさらに使用するためにmyArrayを使用できるようにします。

この前回のSOの投稿は間近に迫っていますが、配列の作成方法については触れていません。Bashでコマンドライン引数を解析するにはどうすればよいですか?

引数を通常のbashスクリプト配列に変換する必要があります。他の言語(Pythonなど)を使用できることはわかっていますが、bashでこれを行う必要があります。「追加」機能または同様の何かを探していると思いますか?

更新:私はまた、ゼロ引数をチェックしてデフォルトの配列値を割り当てる方法を尋ねたかったのですが、以下の回答のおかげで、これを機能させることができました:

if [ "$#" -eq 0 ]; then
  myArray=( defaultarg1 defaultarg2 )
else
  myArray=( "$@" )
fi

回答:


206

実際には、コマンドライン引数は実際にはすでに配列のようです。少なくとも、$@配列のように変数を扱うことができます。つまり、次のように実際の配列に変換できます。

myArray=( "$@" )

いくつかの引数を入力して$@値にフィードするだけの場合は、次を使用しますset

$ set -- apple banana "kiwi fruit"
$ echo "$#"
3
$ echo "$@"
apple banana kiwi fruit

引数の構造の使用方法を理解することは、配列のように他に何もないPOSIX shで特に役立ちます。


2
ありがとう!よく働く!ちょうどゼロ引数をチェックしてデフォルトの配列値を割り当てる方法を尋ねようとしていましたが、$#はそのために完全に機能します!
Suman

1
setスコープの位置パラメータを設定できます。また、シェルオプションを設定することもできます。できますset foo。これは$1、「foo」に展開することを意味しますが、パラメータがダッシュで始まるset場合は、シェルオプションを設定することを意味します。二重ダッシュは、以下のすべてのパラメーターが設定される定位置パラメーターとして解釈されることを保証します。
kojiro 14

11
1つの得点:echo $@すべての引数を出力しますがecho $myArray、最初の要素のみを出力します。それらをすべて表示するには、を使用しますecho ${myArray[@]}
z0r 2015

4
@ z0rこれらの展開を二重引用符で囲まない場合、bashはそれらを再度単語分割し、おそらく意味を失います。
小次郎

配列を「スプラット」して各要素を使用する一般的な方法は、"${myArray[@]}"です。配列をループする場合は、IFSで個々の要素が分割されないように引用符が必要です
BallpointBen

66

多分これは助けることができます:

myArray=("$@") 

また、「in」を省略することで引数を反復できます。

for arg; do
   echo "$arg"
done

同等になります

for arg in "${myArray[@]}"; do
   echo "$arg"
done

3
初心者向けの質問:bashはどのようにargフィールドに入力するかをどのようにして知るのですか?それは事前定義された変数ですか?${var}のコンテンツに展開されvarます。配列${var[n]}の要素nの内容に展開されvarます。され${var[@]}、その後配列全体、すなわちを拡大${var[0]} ${var[1]} ... ${var[n]}(とn最後の要素のインデックスですか)?
クリスチャン

4
[in]なしの[for]は、引数配列$ @($ 1、$ 2など)をループします。[set]コマンドでも設定できます。たとえば、set-arg1 arg2
Nahuel Fouilleul

17

実際には、パラメーターのリストは$1 $2 ...etc
を使用してアクセスできます。これは、以下とまったく同じです。

${!i}

だから、パラメータのリストをセットで変更することができ、
そして${!i}それらにアクセスするための正しい方法は次のとおりです。

$ set -- aa bb cc dd 55 ff gg hh ii jjj kkk lll
$ for ((i=0;i<=$#;i++)); do echo "$#" "$i" "${!i}"; done
12 1 aa
12 2 bb
12 3 cc
12 4 dd
12 5 55
12 6 ff
12 7 gg
12 8 hh
12 9 ii
12 10 jjj
12 11 kkk
12 12 lll

特定のケースでは、これを使用して(配列は必要ありません)、引数が指定されていないときに引数のリストを設定できます。

if [ "$#" -eq 0 ]; then
    set -- defaultarg1 defaultarg2
fi

これは、このさらに単純な式に変換されます。

[ "$#" == "0" ] && set -- defaultarg1 defaultarg2

エコーの例は、echo "$#" "$i+1" "${!i}";表示されているとおりに出力を取得するためのものではありませんか?
Zael

6

ここに別の使い方があります:

#!/bin/bash
array=( "$@" )
arraylength=${#array[@]}
for (( i=0; i<${arraylength}; i++ ));
do
   echo "${array[$i]}"
done

4

簡単ですが、直接操作でき$@ます;)

argsのリストをプロンプトから直接渡す方法は次のとおりです。

function echoarg { for stuff in "$@" ; do echo $stuff ; done ; } 
    echoarg Hey Ho Lets Go
    Hey
    Ho
    Lets
    Go

1
さらに簡単です。次for stuff in "$@" ; do ...と同じですfor stuff ; do ...:)
kkm

1

配列と$ @が実質的に同じである方法を並べて表示します。

コード:

#!/bin/bash

echo "Dollar-1 : $1"
echo "Dollar-2 : $2"
echo "Dollar-3 : $3"
echo "Dollar-AT: $@"
echo ""

myArray=( "$@" )

echo "A Val 0: ${myArray[0]}"
echo "A Val 1: ${myArray[1]}"
echo "A Val 2: ${myArray[2]}"
echo "A All Values: ${myArray[@]}"

入力:

./bash-array-practice.sh 1 2 3 4

出力:

Dollar-1 : 1
Dollar-2 : 2
Dollar-3 : 3
Dollar-AT: 1 2 3 4

A Val 0: 1
A Val 1: 2
A Val 2: 3
A All Values: 1 2 3 4

1

二重引用符の重要性は強調する価値があります。引数に空白が含まれているとします。

コード:

#!/bin/bash
printf 'arguments:%s\n' "$@"
declare -a arrayGOOD=( "$@" )
declare -a arrayBAAD=(  $@  )

printf '\n%s:\n' arrayGOOD
declare -p arrayGOOD
arrayGOODlength=${#arrayGOOD[@]}
for (( i=1; i<${arrayGOODlength}+1; i++ ));
do
   echo "${arrayGOOD[$i-1]}"
done

printf '\n%s:\n' arrayBAAD
declare -p arrayBAAD
arrayBAADlength=${#arrayBAAD[@]}
for (( i=1; i<${arrayBAADlength}+1; i++ ));
do
   echo "${arrayBAAD[$i-1]}"
done

出力:

> ./bash-array-practice.sh 'The dog ate the "flea" -- and ' the mouse.
arguments:The dog ate the "flea" -- and 
arguments:the
arguments:mouse.

arrayGOOD:
declare -a arrayGOOD='([0]="The dog ate the \"flea\" -- and " [1]="the" [2]="mouse.")'
The dog ate the "flea" -- and 
the
mouse.

arrayBAAD:
declare -a arrayBAAD='([0]="The" [1]="dog" [2]="ate" [3]="the" [4]="\"flea\"" [5]="--" [6]="and" [7]="the" [8]="mouse.")'
The
dog
ate
the
"flea"
--
and
the
mouse.
> 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.