我正在使用一个工具(openocd
)打印大量垃圾,然后一个基本进度条缓慢打印简单的点,然后再次打印一些垃圾。
我想过滤此输出,grep
以便仅显示带有进度条的行,并且是实时的(即输出的每个点openocd
立即打印在终端中):
openocd <args> |& grep '^\.'
问题是grep
(最多)是行缓冲的,因此进度条在完成之前不会显示。
我该如何处理grep
,或者是否有任何标准替代方案可以实现此目的?如果有一种通过openocd
配置的方法,这将很有用,尽管我更喜欢更通用的解决方案。
答案1
这是一种黑客/不寻常的答案,事实是这很可能以一种不太干净的方式实现。
grep
本身似乎只在遇到换行符时打印输出,您的进度栏在更新时可能不会引入换行符,因此您的问题。
strace
是一个用于查看命令正在调用的系统调用的工具,这包括向内存/存储读取和写入内容,以及打开/关闭文件描述符等内容。
在管道被传递到 的情况下,您strace
可以查看进程正在访问的内容,因此您可以查看正在馈送到 的文本。将定期发送来自管道命令的输出,您可以嗅探该输出并显示它。我正在测试,这似乎遇到了类似的情况。我使用了因为那是用来显示进度的。stout
grep
strace
grep
strace
rsync --progress
grep
##%
rsync
rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%"
如果你运行这个命令,你会发现它strace
没有很好的输出,但是当我使用它时,它strace
捕获了一些通常不会出现的read
s ,显示s 为 0%、21%、45%、68%, 91% 和 100%,似乎每秒更新一次(可能基于更新进度的频率)。rsync
grep
write
read
rsync
因此,您可以通过再次调用相同的输出来获得不太好的grep
输出。strace
grep
rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%" 2>&1 > /dev/null | grep -o "[0-9]*%"
很2>&1
重要,因为strace
打印在stderr
.重定向> /dev/null
到stdout
以防止报告/dev/null
第一个的输出。grep
最终结果是以下输出:
0%
21%
45%
68%
91%
100%
你必须换掉grep
,但看起来它可以解决问题。它并不漂亮,但它可以工作,并且可以绕过grep
.看起来像grep -f
这样的工作tail -f
会很方便(我知道grep -f
已经在使用了)。
第一个grep
主要只是过滤掉strace
将要read
执行的文本,因为只有匹配的行才会在调用中列出strace
,read
但您还需要一些东西来让文本移动,以便strace
可以观看它。
答案2
我正在花费 Centimane 答案,因为最终答案非常复杂。
它已经很老套了......现在变得非常糟糕:
make flash \
|& strace -e trace=read grep -e "^\." -e rror \
|& stdbuf -o0 sed -ne 's/^.*"\.".*/\./p;/rror/p' \
| stdbuf -o0 tr -d '\n' \
; echo
所以make flash
上面是调用openocd
;
strace
正在使用上面解释的 Centimane 的 hack;
sed
read(0, ".", xxx)
将行替换为单行.
;
tr
将所有的都保持.
在一条线上,最后的回声是放置唯一的 EOL。
除此之外,调用sed
和,将 stdout 缓冲区大小设置为 0(因为 EOL 已删除),并且还匹配在出现错误时打印一些垃圾。tr
stdbuf -o0
grep/sed
(e)rror
我试图将所有这些膨胀因素分解到最低限度,但无法做得更好。
另请注意,我使用的是 zsh/Ubuntu 14.04,我不确定这是否可以在其他 Unix 上运行。