bash 如何阻止 sed 缓冲?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4258177/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 22:58:18  来源:igfitidea点击:

How to stop sed from buffering?

linuxbashsedgrep

提问by User1

I have a program that writes to fd3 and I want to process that data with grep and sed. Here is how the code looks so far:

我有一个写入 fd3 的程序,我想用 grep 和 sed 处理该数据。到目前为止,代码如下所示:


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

Nothing is output until I do a

在我做一个之前什么都不会输出

exec 3>&-

exec 3>&-

Then, everything that I wanted finally arrives as I expected:

然后,我想要的一切终于如我所愿:

I got: data2

It seems to reply immediately if I use only a grep or only a sed, but mixing them seems to cause some sort of buffering. How can I get immediate output from fd3?

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

采纳答案by tchrist

An alternate means to stop sedfrom buffering is to run it through the s2psed-to-Perl translatorand insert a directive to have it command-buffered, perhaps like

一种替代手段来停止sed从缓冲是通过运行它S2P的sed到Perl的翻译和插入一个指令将它命令缓冲的,或许象

BEGIN { $| = 1 }

The other reason to do this is that it gives you the more convenient notation from EREs instead of the backslash-annoying legacy BREs. You also get the full complement of Unicode properties, which is often critical.

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

But you don't need the translator for such a simple sedcommand. And you do not need both grepand sed, either. These all work:

但是对于这样一个简单的sed命令,您不需要翻译器。而且您也不需要grepsed。这些都有效:

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

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

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

Now you also have access to the minimal quantifier, *?, +?, ??, {N,}?, and {N,M}?. These now allow things like .*?or \S+?or [\p{Pd}.]??, which may well be preferable.

现在你也有机会获得最小的量词,*?+???{N,}?,和{N,M}?。这些现在允许状的东西.*?\S+?[\p{Pd}.]??,这可能是优选的。

回答by User1

I think I found it. For some reason, grep doesn't automatically do line buffering. I added a --line-bufferedoption to grepand now it responds immediately.

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

回答by zwol

You can merge the grepinto the sedlike so:

您可以合并grepsed像这样:

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

Unpacking that a bit: You can put a regexp (between slashes as usual) before any sed command, which makes it only be applied to lines that match that regexp. If the first regexp argument to the scommand is the empty string (s//whatever/) then it will reuse the last regexp that matched, which in this case is the prefix, so that saves having to repeat yourself. And finally, the -noption tells sed to print only what it is specifically told to print, and the /psuffix on the scommand tells it to print the result of the substitution.

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

The -eoption is not strictly necessary but is good style, it just means "the next argument is the sed script, not a filename".

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

Always put sed scripts in single quotes unless you need to substitute a shell variable in there, and even then I would put everything butthe shell variable in single quotes (the shell variable is, of course, double-quoted). You avoid a bunch of backslash-related grief that way.

始终把单引号sed脚本,除非你需要在那里替换shell变量,即使这样我会把一切,但在单引号中shell变量(shell变量是的,当然,双引号)。这样你就避免了一堆与反斜杠相关的悲伤。

回答by Alice Purcell

On a Mac, brew install coreutilsand use gstdbuf to control buffering of grep and sed.

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