Bash

從長時間執行的命令的輸出中過濾多個項目

  • August 6, 2017

TLDR:

如何執行 handbrakecli,獲取進度ETA,進入對話框而不閃爍。

細節:

我有一個腳本,它可以在一個目錄中找到所有影片文件,然後一次在它們上執行 handbrakecli。每次 handbrakecli 執行它都會吐出一堆關於文件等的資訊,然後是一行:

Encoding: task 1 of 1, 3.30 % (295.53 fps, avg 303.23 fps, ETA 00h02m54s)

在我的腳本中,我將 handbrakecli 命令傳遞給其他一些命令,以過濾除進度之外的所有內容,然後將其傳遞給對話框,如下所示:

片段 1

HandBrakeCLI --preset "Normal" -i "$f" -o "$DEST" | \
   stdbuf -o0 tr -s '\r' '\n' | \
   stdbuf -o0 grep -oP '(?<=, )\d+(?=\.\d\d \%)' | \
   dialog --gauge "$DIALOG_MSG" 10 70;

這工作正常。它顯示進度並且不閃爍。第二個任務是想出一種方法來顯示進度和預計到達時間,這就是我想出的:

片段 2

HandBrakeCLI --preset "Normal" -i "$f" -o "$DEST_FULL_FILE" | \
   stdbuf -oL tr -s '\r' '\n' | \
   while read -r str; do
       local REMAINING=$(echo "$str" | grep -oP "(?<=ETA )\d\dh\d\dm\d\ds(?=\))");
       local PROGRESS=$(echo "$str" | grep -oP "(?<=, )\d+(?=.\d\d)");
       echo "$PROGRESS" | dialog --gauge "$DIALOG_MSG Time remaining: $REMAINING" 10 70;
   done

這有效,但對話視窗閃爍。我不知道它是否與性能有關(懷疑),或者整個while 讀取循環是否不能很好地與對話框一起使用。

我也嘗試在不通過管道連接到對話框的情況下進行操作,但它只顯示了一次對話框,然後根本沒有更新它。

片段 3

HandBrakeCLI --preset "Normal" -i "$f" -o "$DEST_FULL_FILE" | \
   stdbuf -oL tr -s '\r' '\n' | \
   while read -r str; do
       local REMAINING=$(echo "$str" | grep -oP "(?<=ETA )\d\dh\d\dm\d\ds(?=\))");
       local PROGRESS=$(echo "$str" | grep -oP "(?<=, )\d+(?=.\d\d)");
       dialog --gauge "$DIALOG_MSG Time remaining: $REMAINING" 10 70 $PROGRESS;
   done

最後我嘗試了這個:

片段 4

HandBrakeCLI --preset "Normal" -i "$f" -o "$DEST_FULL_FILE" | \
   stdbuf -o0 tr -s '\r' '\n' | (
       read -r str;                                                                                                                          
       local REMAINING=$(echo "$str" | grep -oP "(?<=ETA )\d\dh\d\dm\d\ds(?=\))");
       local PROGRESS=$(echo "$str" | grep -oP "(?<=, )\d+(?=.\d\d)");
       echo "$PROGRESS";
   ) | dialog --gauge "$DIALOG_MSG Time remaining: $REMAINING" 10 70;

這根本沒有奏效。

我知道這裡有一些基本的問題。

片段 2 是最接近的。dialog --gauge將有選擇地在輸入中查找魔術標記XXX,然後從下一行讀取新百分比,然後從之後的行讀取新提示,直到出現新標記。

所以你應該得到你想要的:

HandBrakeCLI --preset "Normal" -i "$f" -o "$DEST_FULL_FILE" |
stdbuf -oL tr -s '\r' '\n' |
while read -r str
do
   REMAINING=$(echo "$str" | grep -oP "(?<=ETA )\d\dh\d\dm\d\ds(?=\))")
   PROGRESS=$(echo "$str" | grep -oP "(?<=, )\d+(?=.\d\d)")
   echo -e "XXX\n$PROGRESS\n$DIALOG_MSG Time remaining: $REMAINING\nXXX"
done | 
dialog --gauge "$DIALOG_MSG Time remaining: " 10 70;

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