
我正在使用一個工具(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 上運行。