web-dev-qa-db-ja.com

bashコマンドライン引数にアクセスする$ @ vs $ *

多くのSO質問やbashチュートリアルで、bashスクリプトのコマンドライン引数に2つの方法でアクセスできることがわかりました。

$ ~ >cat testargs.sh 
#!/bin/bash

echo "you passed me" $*
echo "you passed me" $@

結果は次のとおりです。

$ ~> bash testargs.sh arg1 arg2
you passed me arg1 arg2
you passed me arg1 arg2

$*$@の違いは何ですか?
前者はいつ使うべきで、後者はいつ使うべきですか。

269
Oz123

特別なパラメータを引用符で囲むと、違いが現れます。違いを説明しましょう。

$ set -- "arg  1" "arg  2" "arg  3"

$ for Word in $*; do echo "$Word"; done
arg
1
arg
2
arg
3

$ for Word in $@; do echo "$Word"; done
arg
1
arg
2
arg
3

$ for Word in "$*"; do echo "$Word"; done
arg  1 arg  2 arg  3

$ for Word in "$@"; do echo "$Word"; done
arg  1
arg  2
arg  3

引用の重要性に関するもう1つの例: "arg"と数の間には2つのスペースがありますが、$ Wordの引用に失敗した場合は、次のようにします。

$ for Word in "$@"; do echo $Word; done
arg 1
arg 2
arg 3

そしてbashでは、"$@"が繰り返し処理される "デフォルト"リストです。

$ for Word; do echo "$Word"; done
arg  1
arg  2
arg  3
359
glenn jackman

Bash Hackers Wikiからの便利で便利な概要表

$* versus $@ table

3行目のcは、$IFSの最初の文字、内部フィールド区切り文字、シェル変数です。

引数をスクリプト変数に格納し、引数にスペースが含まれると予想される場合は、 "$*"トリックを使用することを心からお勧めします。内部フィールドセパレータ$IFSはタブに設定されます

199

$ *

位置パラメータを1から始めて展開します。二重引用符内で展開が行われると、各パラメータの値がIFS特殊変数の最初の文字で区切られた単一のWordに展開されます。つまり、 "$ *"は "$ 1c $ 2c ..."と同じです。ここで、cはIFS変数の値の最初の文字です。 IFSが設定されていない場合、パラメーターはスペースで区切られます。 IFSがnullの場合、パラメータは区切り文字なしで結合されます。

$ @

位置パラメータを1から始めて展開します。二重引用符内で展開が行われると、各パラメータは別々のWordに展開されます。つまり、 "$ @"は "$ 1" "$ 2"と同じです。Word内で二重引用符で囲まれた展開が行われた場合、最初のパラメータの展開は元のWordの先頭部分と結合されます。最後のパラメータの最後の部分は、元のWordの最後の部分と結合されています。位置パラメータがない場合、 "$ @"と$ @は、何も展開されません(つまり、削除されます)。

出典: バッシュマン

41
Muffo

$ @は$ *と同じですが、各パラメータは引用符で囲まれた文字列です。つまり、パラメータは解釈や展開なしでそのまま渡されます。これは、とりわけ、引数リスト内の各パラメータが別々のWordと見なされることを意味します。

もちろん、 "$ @"は引用符で囲む必要があります。

http://tldp.org/LDP/abs/html/internalvariables.html#ARGLIST

15
rkosegi

この例では、atとasterixの違いを強調してみましょう。私は2つの配列を "フルーツ"と "野菜"と宣言しました

fruits=(Apple pear plumm Peach melon)            
vegetables=(carrot tomato cucumber potatoe onion)

printf "Fruits:\t%s\n" "${fruits[*]}"            
printf "Fruits:\t%s\n" "${fruits[@]}"            
echo + --------------------------------------------- +      
printf "Vegetables:\t%s\n" "${vegetables[*]}"    
printf "Vegetables:\t%s\n" "${vegetables[@]}"    

上記のコードの次の結果を参照してください。

Fruits: Apple pear plumm Peach melon
Fruits: Apple
Fruits: pear
Fruits: plumm
Fruits: Peach
Fruits: melon
+ --------------------------------------------- +
Vegetables: carrot tomato cucumber potatoe onion
Vegetables: carrot
Vegetables: tomato
Vegetables: cucumber
Vegetables: potatoe
Vegetables: onion
1
stefansson