$ @がbashで二重引用符と競合するのを防ぐ方法は?

$ @がbashで二重引用符と競合するのを防ぐ方法は?

次の例では、予想される「ab c」の代わりに「ab」を返します。

test() { bash -c "testargs() { echo \$@; }; testargs $@"; }
test "a b" c

これは引用問題のようです。 「$*」を使わずにこの問題をどのように解決できますか?

答え1

$@"$@"ほとんどの文でフォームとしてのみ使用してください。展開すると、最初の位置引数が前に追加され、その後に追加の位置引数を含む"stuff$@"リストが生成されます。stuffたとえば、位置引数がandの場合、fooandbarという2つの単語が得られます。これはあなたの質問の一つです。stufffoobar

もう1つの問題は、使用時にsh -cオプションではなく、最初の引数が使用可能なスクリプト名になることです$0。以降の非オプションパラメータは位置パラメータになります。したがって、sh -c 'echo "$@"' foo bar quxprint-bar quxは  fooin $0barin、$1およびquxinです$2

関数の引数をスクリプトに渡すには、$@スクリプト内で使用します(あなたがしたように、関数内ではなく"stuff$@"二重引用符で関数を実行するシェルで拡張されます)。そして占領$0

test() { bash -c 'testargs() { echo "$@"; }; testargs "$@"' myscript "$@"; }

答え2

二重引用符内の$ @は複数の単語に展開されます。bash -c受け入れるひもパラメーターとして使用されますが、後に他のパラメーターが続くこともあります。性格その後、$ 0で始まる位置パラメータに割り当てられます。

したがって、次のように内部コードにパラメータを送信できますbash -c

Test () { bash -c 'echo $@' -- "$@" ; }
Test "a b" c

これはあなたの場合にも当てはまります。

Test () { bash -c 'testargs() { echo $@ ; } ; testargs $@' -- "$@" ; }
Test "a b" c

複数の単語で構成されるパラメータを保持するには、二重引用符を追加してください。

Test () {
    bash -c 'testargs() {
                 for a in "$@" ; do
                     echo "$a"
                 done
             }
             testargs "$@"' \
        -- "$@"
}
Test "a b" c

すでに存在し、読者に混乱を与える可能性があるTestために使用しました。test

関連情報