如何实时 grep 包含进度条的输出?

如何实时 grep 包含进度条的输出?

我正在使用一个工具(openocd)打印大量垃圾,然后一个基本进度条缓慢打印简单的点,然后再次打印一些垃圾。

我想过滤此输出,grep以便仅显示带有进度条的行,并且是实时的(即输出的每个点openocd立即打印在终端中):

openocd <args> |& grep '^\.'

问题是grep(最多)是行缓冲的,因此进度条在完成之前不会显示。

我该如何处理grep,或者是否有任何标准替代方案可以实现此目的?如果有一种通过openocd配置的方法,这将很有用,尽管我更喜欢更通用的解决方案。

答案1

这是一种黑客/不寻常的答案,事实是这很可能以一种不太干净的方式实现。


grep本身似乎只在遇到换行符时打印输出,您的进度栏在更新时可能不会引入换行符,因此您的问题。

strace是一个用于查看命令正在调用的系统调用的工具,这包括向内存/存储读取和写入内容,以及打开/关闭文件描述符等内容。


在管道被传递到 的情况下,您strace可以查看进程正在访问的内容,因此您可以查看正在馈送到 的文本。将定期发送来自管道命令的输出,您可以嗅探该输出并显示它。我正在测试,这似乎遇到了类似的情况。我使用了因为那是用来显示进度的。stoutgrepstracegrepstracersync --progressgrep##%rsync

rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%"

如果你运行这个命令,你会发现它strace没有很好的输出,但是当我使用它时,它strace捕获了一些通常不会出现的reads ,显示s 为 0%、21%、45%、68%, 91% 和 100%,似乎每秒更新一次(可能基于更新进度的频率)。rsyncgrepwritereadrsync

因此,您可以通过再次调用相同的输出来获得不太好的grep输出。stracegrep

rsync --progress file1 file2 | strace -e trace=read grep "[0-9]*%" 2>&1 > /dev/null | grep -o "[0-9]*%"

2>&1重要,因为strace打印在stderr.重定向> /dev/nullstdout以防止报告/dev/null第一个的输出。grep最终结果是以下输出:

0%
21%
45%
68%
91%
100%

你必须换掉grep,但看起来它可以解决问题。它并不漂亮,但它可以工作,并且可以绕过grep.看起来像grep -f这样的工作tail -f会很方便(我知道grep -f已经在使用了)。

第一个grep主要只是过滤掉strace将要read执行的文本,因为只有匹配的行才会在调用中列出straceread但您还需要一些东西来让文本移动,以便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;

sedread(0, ".", xxx)将行替换为单行.

tr将所有的都保持.在一条线上,最后的回声是放置唯一的 EOL。

除此之外,调用sed和,将 stdout 缓冲区大小设置为 0(因为 EOL 已删除),并且还匹配在出现错误时打印一些垃圾。trstdbuf -o0grep/sed(e)rror

我试图将所有这些膨胀因素分解到最低限度,但无法做得更好。

另请注意,我使用的是 zsh/Ubuntu 14.04,我不确定这是否可以在其他 Unix 上运行。

相关内容