私はこの状況と戦っています:
$ set -- 1 2 3
$ a="$@"
$ echo "$a"
1 2 3
私が驚いたのは課題そのものでした。
man bash
拡張機能について"$@"
次のように言います。
二重引用符内で拡張が発生すると、各引数は別々の単語に展開されます。
したがって、これは次のようになります。
b="1" "2" "3"
bash: 2: command not found
私はこれが"$*"
拡張の目的だと思います。
二重引用符内で拡張が発生すると、IFS特殊変数の最初の文字で区切られた各引数の値を使用して単一の単語に展開されます。つまり、「$*」は「$1c$2c...」と同じです。ここで、cはIFS変数値の最初の文字です。 IFSが設定されていない場合、パラメーターはスペースで区切られます。 IFS が空の場合、パラメーターの連結時に区切り文字は挿入されません。
したがって、次は正確でなければなりません。
$ set -- 1 2 3
$ a="$*"
$ echo "$a"
1 2 3
それでは、"$@"
収益率はなぜ同じですか?この時点では異なるはずです。これがBashの問題ですか、それとも私の誤解ですか?
住宅検査これを次のように検出SC2124。トリガの例を提供することもできます。SC2145。
観察された:
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
4.9.0-6-amd64 #1 SMP Debian 4.9.82-1+deb9u3 (2018-03-02) x86_64 GNU/Linux
答え1
私が知る限り、POSIX$@
未定義割り当て、Bashのドキュメントを除いて、実際にはバグではありません。$@
これは2つの状況で定義されます。
- フィールド分割が実行されるコンテキストで拡張が発生した場合...
- 二重引用符内で拡張が発生した場合、[...]がフィールド分割を実行しない限り、動作は指定されません。 [...] (*)
しかし、
他のすべてのケースでは、拡張結果は次のとおりです。指定されていない。
フィールド分割は、二重引用符なしで割り当てで発生しないため、定義されません。
a="$@"
ここでは、複数の単語に拡張するのと同じように動作すると仮定します。a="$*"
ここでは実際に意味がありません。通常の変数に複数の単語を別のエンティティとして割り当てることはできません。一方の単語を割り当てて残りの単語をコマンド引数として使用すると、混乱してエラーが発生しやすくなります。
"$@"
このシェルチェックページに記載されているように、割り当て動作はシェルによって異なります。 Bash と ksh は位置引数を空白で連結し、zsh と dash は位置引数を最初の文字で連結しますIFS
(まったく"$*"
同じ)。
$ bash -c 'set -- x y z; IFS=.; a="$@"; printf "<%s>\n" "$a"'
<x y z>
$ ksh93 -c 'set -- x y z; IFS=.; a="$@"; printf "<%s>\n" "$a"'
<x y z>
$ zsh -c 'set -- x y z; IFS=.; a="$@"; printf "<%s>\n" "$a"'
<x.y.z>
$ dash -c 'set -- x y z; IFS=.; a="$@"; printf "<%s>\n" "$a"'
<x.y.z>
a="$*"
単一の文字列にリンクする場合、または目的の内容を明示的に作成する場合は、この方法を使用するのが最善です。
(*または拡張に関連するその他の場合${parameter:-word}
)