Linux

向前輸出每一行然後向後輸出的命令

  • September 16, 2019

我正在尋找一個“元命令”xyz,這樣:

(echo "foo"; echo "bar") | xyz rev

將返回:

foo oof
bar rab

我想避免使用臨時文件,即我正在尋找比以下更簡潔的解決方案:

tempfile=$(mktemp)
cat > $tempfile
cat $tempfile | rev | paste $tempfile -

(當然,我想要一個通用的解決方案,對於任何命令,而不僅僅是rev,您可以假設該命令為每個輸入行準確輸出一行。)

Zsh 解決方案也是可以接受的。

由於 stdio 緩衝的工作方式,在大多數情況下會出現很多問題。linux 的一種解決方法可能是使用該stdbuf程序並使用 coproc 執行命令,因此您可以顯式控制輸出的交錯。

以下假設該命令將在每行輸入之後輸出一行。

#!/bin/bash
coproc stdbuf -i0 -o0 "$@"
IFS=
while read -r in ; do
   printf "%s " "$in"
   printf "%s\n" "$in" >&${COPROC[1]}
   read -r out <&${COPROC[0]}
   printf "%s\n" "$out"
done

如果需要更通用的解決方案,因為 OP 只要求程序的每一行輸入最終輸出一行而不是立即輸出,那麼需要更複雜的方法。創建一個事件循環,read -t 0用於嘗試從標準輸入和協同程序中讀取,如果兩者的“行號”相同,則輸出,否則儲存該行。如果在任何一輪事件循環中都沒有準備好,為了避免使用 100% 的 cpu,然後在再次執行事件循環之前引入一個小的延遲。如果該過程輸出部分行,則會出現額外的複雜情況,這些需要被緩衝。

如果需要這個更通用的解決方案,我會使用expect來編寫它,因為它已經很好地支持處理多個輸入流上的模式匹配。但是,這不是 bash/zsh 解決方案。

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