我有这个命令(对于番茄工作法):
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-buffered
,unbuffer
和stdbuf
(看完之后这和这)取得了一些重大进展: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.