それらが引用され、されていない場合$*
と$@
同じです。これらのいずれも使用しないでください。スペースまたはワイルドカードを含む引数があるとすぐに破損する可能性があるためです。
"$*"
は1つの単語に展開され"$1c$2c..."
ます。通常c
はスペースですが、実際にはの最初の文字なIFS
ので、選択するものであれば何でもかまいません。
私がこれまでに見つけた唯一の良い使用法は次のとおりです。
コンマで引数を結合する(シンプルバージョン)
join1() {
typeset IFS=,
echo "$*"
}
join1 a b c # => a,b,c
指定された区切り文字で引数を結合します(より良いバージョン)
join2() {
typeset IFS=$1 # typeset makes a local variable in ksh (see footnote)
shift
echo "$*"
}
join2 + a b c # => a+b+c
"$@"
単語を分割して展開します: "$1"
"$2"
...
これはほとんど常にあなたが望むものです。各定位置パラメーターを個別の単語に展開します。これにより、コマンドラインまたは関数の引数を取得し、別のコマンドまたは関数に渡すのに最適です。また、二重引用符を使用して展開するため"$1"
、スペースやアスタリスク(*
)が含まれていても、問題は発生しません。
さんと呼ばれるスクリプト書いてみましょうsvim
走るvim
とをsudo
。違いを説明するために3つのバージョンを実行します。
svim1
#!/bin/sh
sudo vim $*
svim2
#!/bin/sh
sudo vim "$*"
svim3
#!/bin/sh
sudo vim "$@"
それらのすべては、単純な場合には問題ありません。たとえば、スペースを含まない単一のファイル名:
svim1 foo.txt # == sudo vim foo.txt
svim2 foo.txt # == sudo vim "foo.txt"
svim2 foo.txt # == sudo vim "foo.txt"
ただし$*
、"$@"
複数の引数がある場合にのみ適切に機能します。
svim1 foo.txt bar.txt # == sudo vim foo.txt bar.txt
svim2 foo.txt bar.txt # == sudo vim "foo.txt bar.txt" # one file name!
svim3 foo.txt bar.txt # == sudo vim "foo.txt" "bar.txt"
そして"$*"
、"$@"
スペースを含む引数がある場合にのみ適切に動作します。
svim1 "shopping list.txt" # == sudo vim shopping list.txt # two file names!
svim2 "shopping list.txt" # == sudo vim "shopping list.txt"
svim3 "shopping list.txt" # == sudo vim "shopping list.txt"
したがって"$@"
、常に適切に機能するだけです。
typeset
内のローカル変数を作成する方法であるksh
(bash
そしてash
使いlocal
の代わりに)。これはIFS
、関数が戻るときに以前の値に復元されることを意味します。これは重要です。これは、IFS
標準以外の値に設定されている場合、後で実行するコマンドが適切に動作しない可能性があるためです。