Awk

使用 awk 格式化 grep 輸出。簡單案例和背景案例

  • April 26, 2015

我正在努力解決這個問題。我有這條線:

mplayer *.* 2>/dev/null | grep Playing

它剛剛啟動mplayer,並且只有行匹配列印在螢幕上。每次我更改目前播放的媒體時,這也有效。Playing *filename*

我想知道是否可以“格式化”grep 的輸出。例如,如果輸出是:

Playing Pink_Floyd-Wish_You_Were_Here.mp3  # I get this at the beginning
Playing Pearl_Jam-Once.mp3                 # I get this after I change media inside mplayer

那麼我會有類似的東西:

Mplayer: Playing Pink_Floyd-Wish_You_Were_Here.mp3
Mplayer: Playing Pearl_Jam-Once.mp3

為此,我決定使用 awk:

mplayer *.* 2>/dev/null | grep Playing | awk '{print "Mplayer: "$1}'

但在這種情況下,什麼也沒有發生;我沒有輸出!!!

我的問題不是為了解決 mplayer 的問題,而是為了更深入地了解 bash 中的管道。

例如,如果我使用以下內容:

echo a_song.mp3 | awk '{print "Mplayer: "$1}'

我得到我想要的

Mplayer: a_song.mp3

為什麼第一個命令不起作用?

如果我想在後台執行多個這樣的程序,我該怎麼辦?

當標準輸出為終端時,許多grep實現將使用行緩衝。當標準輸出是終端時,通常是一個互動式會話,您希望盡快獲取數據。因此grep,一旦看到換行符,就會將數據寫入標準輸出。

當標準輸出不是終端時(通常意味著非互動式會話),grep將使用塊緩衝區代替。這意味著grep在看到換行符時不會立即寫入標準輸出。grep在寫入標準輸出之前收集數據量(Linux 中為 4096 字節)。

某些grep版本,例如GNU grepBSD grep具有–line-buffered選項。當看到換行符時,它grep總是寫入標準輸出。所以你的例子變成:

mplayer *.* 2>/dev/null | grep --line-buffered Playing | awk '{print "Mplayer: "$1}'

如果您的grep版本沒有--line-buffer,您可以通過以下方式完成所有操作awk

mplayer *.* 2>/dev/null | awk '/Playing/{print "Mplayer: "$1}'

GNU coreutils 有一個用於修改命令緩衝的工具stdbuf 。您始終可以使用以下命令強制標準輸出中的行緩衝區:

stdbuf -oL command

還有unbuffer命令僅禁用輸出緩衝。

進一步閱讀

引用自:https://unix.stackexchange.com/questions/198597