sed:无法向stdout中写入26个项目:管道损坏

时间:2018-12-09 22:22:20

标签: bash sed

我有以下命令:

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

我想念什么

2 个答案:

答案 0 :(得分:1)

正如@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的整个输出将被读取,并且不会发生错误。

@ptriplee指出,

BTW在管道的开头使用cat是没有用的;您应该awk直接读取文件,如下所示:

awk '{print $1, $6}' input.txt | ...

答案 1 :(得分:1)

方法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

这是蛮力的,将来可能会导致您错过另一个问题。