cassepipe Asked: 2021-10-20 06:54:04 +0800 CST2021-10-20 06:54:04 +0800 CST 2021-10-20 06:54:04 +0800 CST 运行 `cat | 时我不理解 `cat` 的行为 ls` 772 我知道这是一个无用的命令,但我想了解为什么,无论是在bash还是zsh,当我输入时cat | ls,cat会提示我输入,但只会在一行之后返回,而例如</dev/stdin tr -d 'e' | ls让我输入多行直到我点击Ctrl + D? pipe cat 2 个回答 Voted Best Answer ilkkachu 2021-10-20T07:31:07+08:002021-10-20T07:31:07+08:00 这与仅在 1 秒后打印任何内容的原因相同: (echo abc; sleep 1; echo def) | tr -d e |cat 将标准输出重定向到管道后,大多数实用程序开始缓冲输出,并且只有在它们拥有完整的数据块后才在那里写入任何内容。(块的大小是一个实现细节,它可能是几千字节。)您可以使用一些实用程序来禁用缓冲,请参阅:关闭管道中的缓冲。 但是有些实现cat不做缓冲,而是立即写入。这至少包括 GNU 和 Busybox 实现。POSIX 没有指定plaincat对缓冲的作用,只是为了防止缓冲。cat -u 在这里,由于ls没有从标准输入读取任何内容,因此也不会从管道中读取任何内容,因此它可能比您键入任何内容都更快地完成和退出。因此,当cat/tr开始写任何东西时,管道已经关闭,并且 writer 得到一个 SIGPIPE 并退出。由于cat这里会立即写入它读取的内容而无需缓冲,因此它会在第一条输入行之后立即获取信号。另一方面,由于tr等待获得一个完整的缓冲区来写入任何内容,因此第一行输入不会触发它。如果输入了足够多的数据,tr最终也会将其写入管道,获取信号并退出。 就像你说的,管道ls是愚蠢的,因为它不读取任何内容。你可以使用类似true或false代替的东西。 Vilinkameni 2021-10-20T07:27:22+08:002021-10-20T07:27:22+08:00 cat不带参数将从 stdin 读取,等到第一行输入,因为stdin 在引用交互式设备时是行缓冲的,并将其输出到其 stdout,该 stdout 被重定向到ls. ls根本不从标准输入读取,因此它只会将文件列表输出到标准输出并退出。由于ls管道的 -end 由ls(cat的标准输出) 关闭,cat因此也将退出。 任何不从标准输入读取并输出到标准输出的程序都可以观察到相同的行为。例如: cat | uname -a 注: </dev/stdin是多余的。它将标准输入重定向到标准输入。
这与仅在 1 秒后打印任何内容的原因相同:
将标准输出重定向到管道后,大多数实用程序开始缓冲输出,并且只有在它们拥有完整的数据块后才在那里写入任何内容。(块的大小是一个实现细节,它可能是几千字节。)您可以使用一些实用程序来禁用缓冲,请参阅:关闭管道中的缓冲。
但是有些实现
cat
不做缓冲,而是立即写入。这至少包括 GNU 和 Busybox 实现。POSIX 没有指定plaincat
对缓冲的作用,只是为了防止缓冲。cat -u
在这里,由于
ls
没有从标准输入读取任何内容,因此也不会从管道中读取任何内容,因此它可能比您键入任何内容都更快地完成和退出。因此,当cat
/tr
开始写任何东西时,管道已经关闭,并且 writer 得到一个 SIGPIPE 并退出。由于cat
这里会立即写入它读取的内容而无需缓冲,因此它会在第一条输入行之后立即获取信号。另一方面,由于tr
等待获得一个完整的缓冲区来写入任何内容,因此第一行输入不会触发它。如果输入了足够多的数据,tr
最终也会将其写入管道,获取信号并退出。就像你说的,管道
ls
是愚蠢的,因为它不读取任何内容。你可以使用类似true
或false
代替的东西。cat
不带参数将从 stdin 读取,等到第一行输入,因为stdin 在引用交互式设备时是行缓冲的,并将其输出到其 stdout,该 stdout 被重定向到ls
.ls
根本不从标准输入读取,因此它只会将文件列表输出到标准输出并退出。由于ls
管道的 -end 由ls
(cat
的标准输出) 关闭,cat
因此也将退出。任何不从标准输入读取并输出到标准输出的程序都可以观察到相同的行为。例如:
注:
</dev/stdin
是多余的。它将标准输入重定向到标准输入。