我有以下命令:
cat input.txt | awk '{print $1, $6}' | sort -n | uniq -c | sort -nr | sed 's/"//g'| head -10
我得到了想要的输出,但我得到了这个错误
sed: couldn't write 26 items to stdout: Broken pipe
其中input.txt类似于:
192.168.2.20 - - [28/Jul/2006:10:27:10 -0300] "GET /cgi-bin/try/ HTTP/1.0" 200 3395
127.0.0.1 - - [28/Jul/2006:10:22:04 -0300] "GET / HTTP/1.0" 200 2216
我错过了什么
正如@KamilCuk在评论中所说,之所以会发生这种情况,是因为head -10
只从管道中读取前10行(可能还有一些输入缓冲(,然后关闭它;如果输入足够大,则在sed
将所有内容写入管道之前就会发生这种情况(并且管道的缓冲区不够大,无法吸收多余的内容(。因此,这种情况是否发生取决于输入大小、操作系统及其参数(决定管道特性(、sed
在输出下降时的行为等。只要稍微改变一下就足以避免问题,例如:
...sort -nr | tr -d '"' | head -10 # use `tr` instead of `sed` -- it may behave differently
...sort -nr | head -10 | sed 's/"//g' # swap `head` and `sed` -- now `sort`'s output is dropped
这里有一个将避免错误:
...sort -nr | sed '11,$ d; s/"//g'
这样做的方式是,它告诉sed
在输入结束时丢弃第11行("$"(,但由于它在读取它们之后丢弃了(而不是像head -10
那样从一开始就不读取它们(,sort
的整个输出都被读取,不会发生错误。
BTW,正如@triple所指出的,在管道开始时使用cat
是无用的;您应该让awk
直接读取文件,如下所示:
awk '{print $1, $6}' input.txt | ...
方法#1:将sed移动到的末尾
cat input.txt | awk '{print $1, $6}' | sort -n | uniq -c | sort -nr | head -10 | sed 's/"//g'
这在语义上是相同的。通过将sed放在末尾,您可以获得所需的格式,但可以避免出现错误消息。
方法2:忽略错误消息。
cat input.txt | awk '{print $1, $6}' | sort -n | uniq -c | sort -nr | sed 's/"//g' 2>/dev/null | head -10
这是一种蛮力,可能会导致你在未来错过另一个问题。