如何阻止sed缓冲?

时间:2010-11-23 16:16:02

标签: linux bash sed grep

我有一个写入fd3的程序,我想用grep和sed处理这些数据。以下是代码到目前为止的样子:


exec 3> >(grep "good:"|sed -u "s/.*:\(.*\)/I got: \1/")
echo "bad:data1">&3
echo "good:data2">&3

在我做

之前没有输出任何内容

exec 3>&-

然后,我想要的一切终于按照我的预期到达:

I got: data2

如果我只使用grep或者只使用sed,它似乎立即回复,但混合它们似乎会导致某种缓冲。如何从fd3立即获得输出?

6 个答案:

答案 0 :(得分:8)

我想我找到了它。出于某种原因,grep不会自动进行行缓冲。我向--line-buffered添加了grep选项,现在它立即响应。

答案 1 :(得分:4)

阻止sed缓冲的另一种方法是通过the s2p sed-to-Perl translator运行它并插入一个指令让命令缓冲,也许就像

BEGIN { $| = 1 }

这样做的另一个原因是它为您提供了更方便的符号来表示ERE而不是反斜杠 - 令人讨厌的传统BRE。您还可以获得完整的Unicode属性,这通常很重要。

但是你不需要翻译器来完成这么简单的sed命令。而且您也不需要grepsed。这些都有效:

perl -nle 'BEGIN{$|=1} if (/good:/) { s/.*:(.*)/I got: $1/; print }'

perl -nle 'BEGIN{$|=1} next unless /good:/; s/.*:(.*)/I got: $1/; print'

perl -nle 'BEGIN{$|=1} next unless /good:/; s/.*:/I got: /; print'

现在,您还可以访问最小量词*?+???{N,}?{N,M}?。这些现在允许.*?\S+?[\p{Pd}.]??之类的内容,这可能更合适。

答案 2 :(得分:3)

您可以将grep合并到sed中,如下所示:

exec 3> >(sed -une '/^good:/s//I got: /p')
echo "bad:data1">&3
echo "good:data2">&3

解压缩一下:您可以在任何sed命令之前放置正则表达式(像往常一样在斜杠之间),这使得它只应用于与该正则表达式匹配的行。如果s命令的第一个regexp参数是空字符串(s//whatever/),那么它将重用匹配的最后一个正则表达式,在这种情况下是前缀,这样就可以节省自己重复的次数。最后,-n选项告诉sed只打印专门告诉打印的内容,/p命令的s后缀告诉它打印替换结果。 / p>

-e选项不是绝对必要的,但它是好的样式,它只是意味着“下一个参数是sed脚本,而不是文件名”。

除非你需要在那里替换一个shell变量,否则总是将sed脚本放在单引号中,即使这样我也会将所有 shell变量放在单引号中(当然shell变量是,双引号)。你可以避免一堆反斜杠相关的悲伤。

答案 3 :(得分:2)

在Mac上,brew install coreutils并使用gstdbuf来控制grep和sed的缓冲。

答案 4 :(得分:2)

你只需要告诉 grep 和 sed 不要缓冲行:

grep --line-buffered 

sed -u

答案 5 :(得分:0)

Turn off buffering in pipe似乎是最简单,最通用的答案。使用stdbuf(coreutils):

exec 3> >(stdbuf -oL grep "good:" | sed -u "s/.*:\(.*\)/I got: \1/")
echo "bad:data1">&3
echo "good:data2">&3
I got: data2

缓冲还有其他依赖性,例如,取决于mawk或gawk读取此管道:

exec 3> >(stdbuf -oL grep "good:" | awk '{ sub(".*:", "I got: "); print }')

在这种情况下,mawk会保留输入,而gawk不会保留输入。

另请参阅How to fix stdio buffering