5

我需要逐行读取连续数据流(实际上是管道),并且需要在第一行之后退出。在第一行之后。听起来很简单,但是使用“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 等......)

谢谢

4

3 回答 3

8

因为你在使用cat | head -n 1,这是cat 的无用用法,head -n 1. 如果你head -n 1在控制台上这样做,你会得到你想要的行为——head读取一行,打印它,然后退出。

如果你这样做cat | head -n 1,那么会发生这种情况:

  1. cat从其输入中读取“123”。
  2. cat将“123”写入其输出。
  3. head从其输入(连接到cat的输出)读取“123”。
  4. head将“123”写入其输出并退出。
  5. cat从其输入中读取“456”。
  6. cat尝试将“456”写入其输出。
  7. cat得到SIGPIPE,因为其输出另一端的进程已经死亡。
  8. cat退出。

cat将“123”写入 后立即开始另一次读取,直到它尝试向其写入第二行时才head发现它已经死亡。head

于 2012-11-23T22:29:37.590 回答
0

您可以使用 关闭管道control-d。然后输出缓冲区被刷新,head 得到一个 EOF 并在它得到更多输入之前退出。

[s@svr1 ~]$ 猫 | 头 -n 1
123
123
control-d
[s@svr1 ~]$

head读完第一行后停止。你可以用

[s@svr1 ~]$ 猫 | 头-n 1

然后做 a ps aux | grep -w -e cat -e head,这会产生

... 猫
... 头
... grep -e 猫 -e 头

然后输入

123
123

然后再做ps aux | grep -w -e cat -e head一次,这会产生

... 猫
... grep -e 猫 -e 头

瞧,头不见了。因此,当它尝试编写第二行时,它不是在头上徘徊,而是 cat 在收到 EPIPE 后中止。

于 2012-11-23T22:13:21.533 回答
0

有人可以解释(首先)为什么会这样吗?

cat在未指定文件名时使用STDIN- 所以它正在等待你给它第二行或 ^D.

您可以使用 sed -n 1p filename 仅抓取第一行或sed '1!d' filename删除除第一行之外的所有内容。

于 2012-11-23T22:35:25.990 回答