web-dev-qa-db-ja.com

入力がパイプを経由する場合、追加の改行を待機する「読み取り」コマンド

単にreadを実行すると、1行を読み取り、 Enter が押されます。

$ read
typing something here
$

ただし、パイプを介して入力を渡すと、 from catreadは動作が異なり、2番目の改行に遭遇するまで実行を続けます。

$ cat | read
typing first line
typing second line
$

なぜこのようになっているのか誰にも説明できますか?

PS:この質問は に触発されました。標準入力をフィードし、同時にファイルにダンプする方法は?

3
Byte Commander

改行とは何の関係もありません。

straceを使用してコマンドを実行すると、catが終了する前に、最後にSIGPIPEを受け取ることがわかります。

$ strace cat | read

...
someOutput
...
+++ killed by SIGPIPE +++
  1. 最初のcatコマンドが実行されます。
  2. 次に、何かを初めて入力して、 Enter
  3. 入力したものはreadにパイプされます。
  4. catはまだ実行中で、EOFを待機しています。
  5. 他の何かを入力してから Enter アジアン。
  6. 今回は、readにパイプすることはできません。これは、次のように実行しない限り、入力を待機するreadがなくなったためです(最初のパイプの後に閉じられました)。

    cat | while read line; do echo $line; done;
    
  7. catSIGPIPEを受け取り、閉じられます。

プロセスは、リーダーが残っていないタイプのSOCK_STREAMのパイプ(名前付きまたは名前なし)またはソケットに書き込もうとすると、SIGPIPEを受け取ります。 [1]

2番目のパイプが発生すると、SIGPIPEを受信しますafterが発生します。

たとえば、yesコマンドは、yesのようなコマンドが高速で繰り返しパイプするため、考えてみてください。

yes | read

2番目のパイプの直後に閉じられます。2つのwrite()呼び出しに注意してください。

close(3)                                = 0                    
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = 8192          
write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = -1 EPIPE (Broken pipe) 
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=3542, si_uid=1000} ---
+++ killed by SIGPIPE +++

yesコマンドは速すぎるため、2つ以上のwrite()コールが表示される場合がありますが、複数回実行すると、少なくとも2つのコールが表示され、1つは表示されません。

2
Ravexina