4

私が理解して読んでいると、$@「arg1」「arg2」「arg3」に変わります。
しかし、引用すると、場合によっては奇妙な動作をするようです。
 

テスト1、$ @

$ function somefunc { sh -c "echo $@"; }
$ somefunc 1 2 3
> + somefunc 1 2 3
> + sh -c 'echo 1' 2 3
> 1

期待される出力は123で、取得する出力は1です。これで、何らかの理由でecho 1コマンドとしてのみ渡されるように見えますが、なぜ"echo "1" "2" "3""それになるのでしょうか。echo 「beforeecho」が「before1.Test 2、$ * 」によって閉じられる可能性があるため、私はおそらく予想していました。
 

$ function somefunc { sh -c "echo $*"; }
$ somefunc 1 2 3
> + somefunc 1 2 3
> + sh -c 'echo 1 2 3'
> 1 2 3

これは非常に明白であり、念のために機能します。結局のところ、$*では1 2 3なく"1" "2" "3"
 
テスト3、$@および$*

$ function somefunc { sh -c "echo $@ $*"; }
$ somefunc 1 2 3
> + somefunc 1 2 3
> + sh -c 'echo 1 2 3 1 2 3'
> 1 2 3 1 2 3

これはまた奇妙なことに十分に機能するようです。しかし、私はどのよう"echo "1" "2" "3" 1 2 3"に変化するのかわからず'echo 1 2 3 1 2 3'、それだけの「パターン」に従わない"echo $@"
 

テスト4、$@と文字列

$ function somefunc { sh -c "echo $@ hi"; }
$ somefunc 1 2 3
> + somefunc 1 2 3
> + sh -c 'echo 1' 2 '3 hi'
> 1

これもまた、考えても、結局のところ文字列に変わる"echo $@"のとほとんど同じです。 また、私を困惑させるのは、それがに変わったことです。最初のテストでは、 (周囲の2つがなければ)"echo $@ $*"$*
'echo 1' 2 '3 hi''echo 1' 2 3 hi'3 hi

テスト5、$@および$var

$ var="hi"
> + var=hi
$ function somefunc { sh -c "echo $@ $var"; }
$ somefunc 1 2 3
> + somefunc 1 2 3
> + sh -c 'echo 1 2 3 hi'
> 1 2 3 hi

これは再び機能します。したがって$@、別の変数がそれに続く場合は機能するようです。

テストは、の代わりに、su user -cまたはbash -cその代わりに行うこともできるsh -cので、次の指定された引数を実行する他のすべてのコマンドもあると思います。

私は今、それからある種の行動を得たようです
が、私はまだこの行動を理解していません。
ここで何が欠けていますか?

4

3 に答える 3

2

sh言語の仕様には、次のように書かれてい$@ます。

1つから開始して位置パラメータに展開します。展開が二重引用符で囲まれ、フィールド分割(フィールド分割を参照)が実行される場合、各位置パラメーターは個別のフィールドとして展開されます。ただし、最初のパラメーターの展開は、元の単語(展開されたパラメーターが単語内に埋め込まれていると仮定)、および最後のパラメーターの展開は、元の単語の最後の部分と引き続き結合されます。位置パラメータがない場合、「@」を展開すると、「@」が二重引用符で囲まれている場合でも、ゼロフィールドが生成されます。

これは "echo $@ $*"、位置パラメータが、、である文字列がに1展開23れる必要があることを意味し"echo 1" "2" "3 1 2 3"ます。これにより、テスト3は文字列を出力する必要があります1。bashが文字列を誤って展開して"echo 1 2 3 1 2 3"出力するという事実は、bash1 2 3 1 2 3のバグを示しています。

sh文法規則のこの(さらに別の)奇妙なことに対処するための通常の手法は、それが別個の単語である場合にのみ二重引用符で$@を使用することです。つまり、を記述してもかまい"$@"ませんが$@、二重引用符で囲まれているのがそれだけでない限り、二重引用符で囲まないでください。

于 2012-06-30T16:45:55.680 に答える
1

@BrianSwiftのヒントを使用すると、Test3を除いてすべてが完全に理にかなっています(ここでは、最初にプレフィックスがあり、3番目にサフィックスが付いた3つの引数を取得するわけではありません。代わりに、結果は単一の引数になります) 。'echo '' $*'

$@しかし、それはおそらく、との両方$*がシェルに特別なコードが存在する「特別な」変数であるという事実で説明されるかもしれません。後で評価されるため、の存在は$*@BrianSwiftによって通知された特別な動作をオーバーライドするだけだと思います。$*

順序を入れ替えてみてください:somefunc() { sh -x "echo $* $@"; }。上記の仮定をサポートしているように見える、prefix-with-prefix-and-suffixの動作が再び得られます。

結論として、動作がおそらく少し「文書化されていない」Test3を除いて、すべてがマニュアルを参照して説明できます。

于 2012-06-30T12:25:59.680 に答える
0

私が理解して読んでいると、$@は"arg1""arg2""arg3"に変わります。

いいえ、"$@"になり"arg1" "arg2" "arg3"ます。引用符は重要です。

于 2012-06-30T00:54:13.447 に答える