web-dev-qa-db-ja.com

パイプの途中で「ヒアドキュメント」を使用するにはどうすればよいですか?

ヒアドキュメントをテンプレートとして使用して、いくつかのコンテンツを生成したいと思います。

passphrase=$(<passphrase) envsubst <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: openshift-passphrase
stringData:
  passphrase: ${passphrase}
EOF

oc create -f -にパイプします。

EOFの後にパイプを追加すると、機能しません。

変数置換を使用してヒアドキュメントをそれを消費するものにパイプするにはどうすればよいですか?

1
simbo1905

まず、_<<_の直後にEOFの任意の部分を引用する必要があります。最も自然な方法は_<<"EOF"_ですが、_<<E"OF"_または_<<""EOF_でもかまいません。これがないと、envsubstは_${passphrase}_がすでに展開されている文字列を取得します。 envsubstはリテラル_$foo_または_${foo}_サブストリングを持つ文字列を操作するため、事前にそれらを展開すると、envsubstは何の関係もありません。さらに、あなたの場合、コード内の変数定義はシェル自体ではなくenvsubstにのみ影響するため、シェルはおそらく_${passphrase}_を空の文字列に展開します。同じ名前の変数が(誤って?)事前にシェルに設定されていない限り。

今、私たちはあなたの明確な質問に行き着きます。結果を任意のコマンドにパイプすることができますが、それでも最後のEOFを別の行に保持する必要があります。これを行う1つの方法は、次のとおりです。

_passphrase=$(<passphrase) envsubst <<"EOF" | oc create -f -
apiVersion: v1
kind: Secret
metadata:
  name: openshift-passphrase
stringData:
  passphrase: ${passphrase}
EOF
_

または、サブシェルにあるコードを実行することもできます。

_( passphrase=$(<passphrase) envsubst <<"EOF"
apiVersion: v1
kind: Secret
metadata:
  name: openshift-passphrase
stringData:
  passphrase: ${passphrase}
EOF
) | oc create -f -
_

Bashリファレンスマニュアル

パイプラインの各コマンドは、独自のサブシェルで実行されます

したがって、最初のソリューションでも、_( )_なしでパイプを構築できた場合、その最初の部分(_|_の前)はとにかくサブシェルで実行されます。 2番目の解決策は、このサブシェルを明示的にします。明示的な_(_を使用した後、シェルは明示的な_)_を待機します。これにより、終了EOFの後に何かを配置できます。

驚くべきことに、最初のソリューションでも、単一の複合コマンドで複数のヒアドキュメント(_<<_)を使用できます。このようなリダイレクトはパイプではほとんど意味がありませんが、_&&_および_||_で役立つ場合があります。

_command1 <<EOF && command2 <<EOF || command3 <<EOF
content1
EOF
content2
EOF
content3
EOF
_

明示的なサブシェルを使用して、同じように再配置しました。

_( command1 <<EOF
content1
EOF
) && ( command2 <<EOF
content2
EOF
) || command3 <<EOF
content3
EOF
_

状況によっては、一方の表記をもう一方の表記よりも優先する場合があります。

特定の例に戻ります。サブシェルを使用すると、envsubstも必要ありません。

_( passphrase=$(<passphrase); oc create -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: openshift-passphrase
stringData:
  passphrase: ${passphrase}
EOF
)
_

この方法と前の2つの方法には興味深い違いがあります。

  • 今回は、サブシェル自体が_${passphrase}_を展開する必要があるため、_<<EOF_ではなく_<<"EOF"_になります。
  • これが機能するためには、変数がocだけでなく、サブシェルにも認識されている必要があります。これは、… passphrase=$(<passphrase) oc create -f - <<…(セミコロンがないことに注意)が機能しないことを意味します。
  • 技術的には、サブシェルにない(つまり、_( )_がない)同じコードも機能しますが、変数はメインシェルに残ります。サブシェルでコードを実行すると、変数はそれとともに消滅します。元のコードでは、変数はメインシェルに設定されていないので、これが必要なものだと思います。
2