例如
# this line should output ssh banner
nc localhost 22
# this line should output the same string expect the replacements
nc localhost 22|sed 's/SSH/XXX/g'
nc localhost 22 > foo # after killing the process, I can see the banner in file `foo`
nc localhost 22|sed 's/SSH/XXX/g' > foo # however I see nothing when sed is used
如前所述,如果我使用sed
管道传输nc
的输出,则sed
无法将 的输出重定向到文件。
我还尝试了其他命令来传递结果,例如grep
, tr
,相同的结果。
但是,cat
可以将结果通过管道传输到文件。奇怪的..
nc localhost 22|cat > foo
那么为什么会发生这种情况呢?cat
在这种情况下和其他命令有什么区别?我怎样才能将sed
输出重定向到文件cat
?
答案1
$ 猫 | sed -e 's/foo/bar/' > 输出.txt 富 ^C $猫输出.txt [没有什么]
但:
$ 猫 | sed -e 's/foo/bar/' > 输出.txt 富 ^D $猫输出.txt 酒吧
对文件的写入(但不是对终端)通常由 C 库(stdio 函数)缓冲到数千字节的块。如果您按 Ctrl-C 来终止管道,则sed
在管道终止之前将没有时间写出缓冲区,因此生成的输出文件为空。(你可以说这是 C 库中的一个错误,它没有捕获终止信号,但事实就是如此。)
Plaincat
可能不使用 stdio,因为它不处理任何复杂的东西,比如线条。类似的东西cat -n
可能会有所不同,也可能不会。
您可以进行安排,以便不需要使用 Ctrl-C 终止管道,而是让它自行完成。至少在 my 中nc
,该-qN
选项告诉它在之后退出氮stdin 关闭后的秒数,因此例如:
$ printf '' | nc -q0 localhost 22 | sed 's/SSH/FOO/' > output.txt
$ cat output.txt
FOO-2.0-OpenSSH_7.4p1 Debian-10+deb9u7
或者,至少有几种方法可以关闭缓冲,请参见例如 关闭管道中的缓冲和 用于删除标准输出缓冲的“unbuffer”或“stdbuf”?
GNU sed 也有-u
/--unbuffered
开关
从输入文件加载最少量的数据并更频繁地刷新输出缓冲区