ヒアドキュメントとパイプを組み合わせると失敗する

ヒアドキュメントとパイプを組み合わせると失敗する

curl を使用して API にログインしようとしています。リクエストは JSON を期待しているため、以下を使用します。

curl -s -X POST -H "Content-Type: application/json" \
    $API_URL/auth -d@- <<EOF
{
  "id": "[email protected]",
  "password": "!password!"
}
EOF

...そして、それはうまく機能しています。次のような結果が得られます。

{"access_token":"jXed...I5mQ=","expires_in":3600}

しかし、出力を変数にキャプチャしようとすると、機能しません。

私はもう試した:

x=$(curl ...)

...しかし、それは失敗するbash: !password!: event not found

はい、パスワードするで始まります!。これは API のテスト インストールなので、弱いパスワードを使用しています。

set +Hを使用したり、スクリプトからこれを実行したりすると、bash は に対して何も行わないことはわかっています!。問題は次の点です。

  1. 時々、スクリプトをコマンド ラインにコピー アンド ペーストしたいことがあります。6 か月後には、この面倒なことは忘れてしまうでしょう。
  2. なぜ bash はヒアドキュメント内でこれを実行しようとしているのでしょうか?

前述の の奇妙さのため!、代わりに に結果をパイプしてみましたread:

(curl ...
EOF
) | read x

...しかし、その後、何らかの理由でヒアドキュメントが破損し、サーバーは「無効な JSON」と同等の応答を返します。

catちなみに、の代わりにを使用するとcurl、ヒアドキュメントは空になるようです。

答え1

エラーを回避するにはevent not foundset +Hスクリプト内で を使用するだけです。これは無害であり、それを説明するコメントを追加できます。

| read x単純に機能しません。http://tiswww.case.edu/php/chet/bash/FAQ、 具体的には:

E4) コマンドの出力を `read variable' にパイプした場合、read コマンドが終了したときに出力が $variable に表示されないのはなぜですか?

bash では、サブシェルで| foo実行されます。親シェルの変数を変更することはできません。foo

代わりに使用してくださいx=$(whatever)

関連情報