如果通过管道输入,则“read”命令等待额外的换行符
如果我只是运行read
它会读取一行并在按下Enter时立即退出。
$ read typing something here $
但是,当我通过管道(例如来自cat
传递输入时, read
行为会有所不同并继续运行,直到遇到第二个换行:
$ cat | read typing first line typing second line $
谁能解释为什么会这样?
PS:这个问题的灵感来自如何提供标准输入并同时转储到文件中?
它与换行没有任何关系。
如果你使用strace
运行你的命令,你会发现cat
会在关闭之前收到一个SIGPIPE
:
$ strace cat | read ... someOutput ... +++ killed by SIGPIPE +++
- 第一个
cat
命令开始运行。 - 然后你第一次输入内容并按Enter键 。
- 您键入的内容将通过管道传输到
read
。 -
cat
还在跑步,等待EOF。 - 您输入其他内容然后点击Enter agian。
-
这次,它无法通过管道
read
,因为没有read
等待输入(它在第一个管道之后已经关闭),除非你像这样运行它:cat | while read line; do echo $line; done;
-
cat
将收到一个SIGPIPE
并被关闭。
当一个进程尝试写入一个没有读取器的SOCK_STREAM类型的管道(命名与否)或套接字时,它会收到一个SIGPIPE。 [1]
接收SIGPIPE
发生在第二个管道发生之后。
例如,考虑yes
命令,因为像yes
这样的命令yes
快速重复地输入:
yes | read
它在第二个管道后立即关闭,注意两个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
命令太快,你可能会看到两次以上的write()
调用,但是如果你多次运行它,你将看到至少两次调用,而不是一次。