我需要逐行从连续数据流(实际上是管道)中读取,并且我需要在第 1 行之后退出。就在第一行之后。听起来很简单,但是使用"head -n 1",我注意到我实际上需要在 head 退出之前输入第二行。
测试用例:
[s@svr1 ~]$ cat | head -n 1
123 <- I type this first (followed by enter, of course)
123 <- I get this output from head, but the command does no exit
456 <- Then I need to type this for the command to exit and bring me back to the prompt
[s@svr1 ~]$
有人可以解释(首先)为什么它会那样做,也许我如何才能得到我需要的东西?(我想坚持基本的 Linux/Unix 轻量级构建块。没有Perl,Python之类的...
谢谢
因为你使用的是cat | head -n 1
,这是对cat的无用用,与head -n 1
不同。如果你在控制台上head -n 1
,你会得到你想要的行为 - head
读取一行,打印它,然后退出。
如果您执行cat | head -n 1
,则会发生以下情况:
-
cat
从其输入中读取"123"。 -
cat
将"123"写入其输出。 -
head
从其输入(连接到cat
的输出)读取"123"。 -
head
将"123"写入其输出并退出。 -
cat
从其输入中读取"456"。 -
cat
尝试将"456"写入其输出。 -
cat
之所以SIGPIPE
,是因为其输出另一端的进程已经死亡。 -
cat
退出。
cat
一写"123"就开始另一次读取head
,直到它试图写第二行,它才发现head
已经死了。
您可以使用 control-d 关闭管道。然后刷新输出缓冲区,磁头获得EOF并在获得更多输入之前退出。
[s@svr1 ~]$ 猫 | 头 -n 1
123
123
控制-D
[s@svr1 ~]$
head
阅读第一行后停止。您可以通过以下方式进行验证
[s@svr1 ~]$ 猫 | 头 -n 1
然后做一个ps aux | grep -w -e cat -e head
,得到
。 猫
... 头
... grep -e cat -e head
然后输入
123
123
然后再次执行ps aux | grep -w -e cat -e head
,结果为
。 猫
... grep -e cat -e head
瞧,头不见了。所以它不是头徘徊,而是猫在收到 EPIPE 后中止,当它试图写第二行时。
有人可以解释(首先也是最重要的)为什么它会那样做吗?
当未指定文件名时,cat
使用STDIN
- 因此它正在等待您为其提供第二行或^D。
您可以使用 sed -n 1p filename
仅抓取第一行,sed '1!d' filename
删除除第一行之外的所有内容。