区切り文字内で「$@」を拡張

区切り文字内で「$@」を拡張

次のスクリプト1を検討してください。

#!/bin/bash
bash <<END
printf "%s\n" "$@"
END

驚くべきことに、(私にとっては)$@ここでドキュメントの内部が最初に展開され、次に引用されるので、出力は次のようになります。

$ /tmp/test.sh "a a" b c
a a b c

引用符を削除すると、単純な$@動作が発生します。

$ /tmp/test.sh "a a" b c
a
a
b
c

どちらのオプションも希望の出力を提供しません。同様の配列を試しましたが、args=("$@")拡張は同じように機能します。 「結果」を次の変数に入れようとしましたが、args="$@"これは「aab c」のみを返します。

出力を以下のようにする方法についてのアイデアはありますか?

a a
b
c

1明らかにこれは非常に簡単です。実際、私はheredocを使ってスクリプトを実行していますが、docker runこの質問では問題ありません。

答え1

ここのドキュメント、シェルは「ドル置換」(、、$fooおよび$(some command)バックスラッシュで保護されています)`some command`を実行します。ここでは、ドキュメントは二重引用符で囲まれた文字列のように展開されます。これを防ぐには、ここのドキュメントの閉じるタグに引用符を使用してください。これにより、ドキュメントは一重引用符で囲まれた文字列のように動作します(まったく拡張されません)。$((x+1))\`$

bash <<'END'
printf "%s\n" "$@"
END

"$@"これは内部bashによって拡張され、引数を受け取らないため、目的の操作を実行しません。実際のユースケースで動作する場合と動作しない場合がある最も簡単な直接的な解決策は、パラメータを内部でbashに渡すことです。

bash /dev/stdin "$@" <<'END'
printf "%s\n" "$@"
END

実際のユースケースで内部的にbashに引数を渡すことができない場合は、環境変数を介して渡すことができます。ただし、環境変数ごとに1つの文字列しか渡すことができないため、渡す必要がある文字列の数が可変の場合は便利ではありません。

export widget_count="$1" data_source="$2" frobnicator="$3"
bash <<'END'
printf "%s\n" "$widget_count" "$data_source" "$frobnicator"
END

最後の手段として、これらの値を参照として渡す必要があるかもしれません。シェル構文を引用する文字列:

  1. 'に交換してください'\''
  2. '始めと終わりに追加されました'

答え2

問題は目的の出力を取得する方法なので、これがあなたの目的に適していると思います。

関数内で、目的の印刷ステートメントを次のように宣言してみました。

function test_function {
    printf "%s\n" "$@"
}

次に、希望の入力でbashで実行します。

bash-3.2$ function test_function {
>     printf "%s\n" "$@"
> }
bash-3.2$ cat << EOF
> $(test_function "a a" b c)
> EOF
a a
b
c

関連情報