CLI 行缓冲区:如何通过管道将输出流传送到 grep?

CLI 行缓冲区:如何通过管道将输出流传送到 grep?

我有这个命令(对于番茄工作法):

play -n synth 25:00 pinknoise

我不想完全静音输出(-q选项),只想静音标题(grep不起作用)。

正常输出:

File Size: 94.3T     
 Encoding: n/a           
 Channels: 1 @ 32-bit   
Samplerate: 48000Hz      
Replaygain: off         
 Duration: unknown      

In:0.00% 00:00:01.02 [00:00:00.00] Out:49.2k [======|======] Hd:1.3 Clip:0 

期望过滤输出:(01.02此数字会更新,就像在 cURL 或pv进度条中一样)

我怎样才能只 grep 输出的这一部分?

迄今为止:

  • 由于某种原因,输出被发送到 stderr,例如来自 的“权限被拒绝” find。一种简单的测试方法是在末尾添加2> /dev/null

    也许 sox/play 输出到 stderr 的原因是因为它支持使用特殊文件名将输出写入标准输出 (stdout) -(参见sox 手册页)。

  • |& grep "^In"不起作用。使用|& tee log.txt它似乎使用了删除字符更新最后一行。

    我试过grep --line-bufferedunbufferstdbuf(看完之后)取得了一些重大进展:

      play -n synth 25:00 pinknoise  2>&1 | stdbuf -oL tr '\r' '\n' | grep -o '[0-9][0-9]*\.[0-9][0-9] '
    

非常接近了!

是否可以像原始输出一样只获取一行更新内容?也许就像这个循环echo -ne

我不确定为什么类似这样的方法| grep --line-buffered .不起作用,也无法删除尾随换行符:| tr -d '\n'。我需要类似这样的方法tail -f -n 1

答案1

如果你也通过管道传输 stderr,那么你可以 grep 输出,例如:

$ play -n synth 25:00 pinknoise |& grep File
 File Size: 2.52G

管道部分GNU Bash 手册:

如果|&使用' ',命令1的标准错误,除了它的标准输出外,还连接到命令2通过管道将 的标准输入重定向到 ;它是 的简写2>&1 |。在命令指定的任何重定向之后,将标准错误隐式重定向到标准输出。

但是,这对于进度行不起作用:CLI 命令通常会测试输出是否到终端,如果不是,则丢弃更新的输出。我们需要一个 hack 解决方法来解决这个问题。首先将完整输出重定向到文件:

play -n synth 25:00 pinknoise &>sox.log

这将阻止当前终端,您可以不是只需将其发送到后台,因为这样它会再次丢弃进度行。因此,要获取此行,请在同一目录中打开第二个终端并处理文件,例如:

$ grep In sox.log
In:0.00% 00:00:03.24 [00:00:00.00] Out:156k  [======|======] Hd:0.8 Clip:0
$ tail -n+10 sox.log; echo
In:0.00% 00:00:10.24 [00:00:00.00] Out:492k  [!=====|=====!] Hd:1.7 Clip:0

使用的优点tail是退出Aborted.时您还可以获得以下行play

$ tail -n+10 sox.log;echo
In:0.00% 00:00:12.80 [00:00:00.00] Out:614k  [======|======] Hd:0.7 Clip:0    
Aborted.

相关内容