スクリプトをbashにパイプするときに「stdin」から読み取るために「read」を使用できないのはなぜですか?

スクリプトをbashにパイプするときに「stdin」から読み取るために「read」を使用できないのはなぜですか?

私はこの問題に対する解決策や解決策を探していません。ジェジュンのようにダメだから幸いだbash。私は理解できません。なぜ動作しません。

次のスクリプトが機能しない理由の詳細な回答を探しています。 unix.stackexchange.comの投稿を含む、以前のすべてのインターネット検索では問題を実際に解決できませんでした。すでにパイプを介して「インポート」(?)されているため、read読み取りがstdin機能しないことに関連していますか?stdincatbash

Bashスクリプトの例test.sh:

echo "Please say name:"
read NAME
echo "Hello $NAME"

方法1スクリプトを呼び出しますbash test.sh

$ bash test.sh
Please say name:
XYZ
Hello XYZ
$

方法2パイプラインを介してスクリプトを実行しますbash

$ cat test.sh | bash
Please say name:
$

したがって、スクリプトは入力を待つか、2行目を印刷せずにすぐにプロンプ​​トに戻ります。

答え1

あなたしたstdinから読み込み中ですが、read標準入力から次の行を読み込んでいますecho "Hello $NAME"。つまり、その行を読み込んだ後は入力がなくなり、実行するコマンドはなくなり、スクリプトは終了します。

持つ単一標準入力ストリームをコードとデータの両方に使用しようとしています。これは、対話型bashセッションが入力、read応答、および標準入力を使用するために実行する他のコマンドからコマンドを読み取るのと同じ方法です。

スクリプトの最後に追加の行を追加すると、これが起こるのがわかります。

echo "Please say name:"
read NAME
echo "Hello $NAME"
printf 'name=%s\n' "$NAME"

これは両方とも、スクリプトが続行することを確認するための追加のコマンドを提供し、次に読んだ内容を示していますNAME

Please say name:
name=echo "Hello $NAME"

変数が残っているのを見ることができます文字通りスクリプトファイルに書き込まれた内容 - 変数の補間、実行、または拡張は行われません。


read端末でこれを行う場合は可能です。最も簡単な方法は、TTYに接続されている標準入力(!)の代わりに標準出力から読み取ることです。

read NAME <&1

これは私が何かを入力するのを待ってから、プログラムの残りの部分を続けます。/dev/ttyまたはを使用することもできます$(tty)

関連情報