awk 出力には追加のキャリッジリターンがあり、バッファリングされます。

awk 出力には追加のキャリッジリターンがあり、バッファリングされます。

私の究極の目標は、fdkaacでコーディングしたときにzenity進行ダイアログを取得することです。

最初は、Lameを使用して「aa.wav」を「aa.mp3」にエンコードするときに正しく機能するいくつかのコードで始めました。これにより、進行状況バーは0から100%までシームレスに更新されます。

lame -m auto -V 4 aa.wav aa.mp3 | awk -vRS='\r' '(NR>3){gsub(/[()%|]/," ");print $2; fflush();}' | zenity --progress --title="Title" --text="encoding" --auto-close

次に、fdkaacを使用してこのコードを実行します。

fdkaac --profile 2 --bitrate-mode 5 aa.wav -o aa.aac

すると、エンコードが終了すると画面が出力されます。
[100%] 05:31.227/05:31.227 (43x), ETA 00:00.000
14607096/14607096 サンプルが 00:07.689 で処理済み

エンコード中に最初の行が印刷され、[100%]はエンコード中に0から100までシームレスに更新されます。エンコードの終わりに2行目を印刷します。

これに基づいてgsub検索を修正し、gsub(/[[%]/," ")に置き換えてデータを選択しました。

次に、次のコードを実行します。

fdkaac --profile 2 --bitrate-mode 5 aa.wav -o aa.aac 2>&1 | awk -vRS='\r' '(NR>3){gsub(/[\[%]/," ");print $1; fflush();}' | zenity --progress --title="Title" --text="Encoding" --auto-close

結果は私が期待していたものとは異なりました。進行状況ダイアログボックスに0%が表示されます...一定時間が経過すると50%にジャンプし、エンコードが完了すると消えます。

だから私は次のコードを使ってzenityに入ってくるデータを見ました。

fdkaac --profile 2 --bitrate-mode 5 aa.wav -o aa.aac 2>&1 | awk -vRS='\r' '(NR>3){gsub(/[\[%]/," ");print $1; fflush();}' 

画面出力が予想したものとは異なります。 1から50までが同時にすべて印刷されますが、連続した行に印刷され、エンコードが完了すると、50から100までの連続した行に別々に印刷されます。

1
2
3
4
5

...

48
49
50

そして50まで続く。その後、出力は別の行に50から100まで続きます(再び同時に印刷されます)。

50
51
52

..

98
99100

したがって、問題は明らかです。出力データは2つのバッチで印刷されます(ダイアログボックスに表示されます)。そして、データは連続した行に表示されます。 (awkフィルタの後の誤った出力はすべて同じ行に印刷され、シームレスに更新されます。)

問題は追加のキャリッジリターンに関連していると思われますが、それを取り除く方法がわかりません。 -vRS='\r コマンドを削除しようとしましたが、まったく出力が提供されませんでした。

置換を理解できません: RS='\r'。変数RSはどこに現れますか?

データを出力してみると、正確に50%と100%であるのも驚きです。なぜ38%または67%ではないのですか? ..データが私に何かを教えてくれましたが、それが何なのかはよくわかりません。

ベストアンサー1

問題は、fdkaac出力がパイプに移動しながら出力をバッファリングすることです。コマンドの前に以下を付けてみてください。

stdbuf -o 0 -e 0 fdkaac ... 2>&1 | ...

そのうち、-o は stdout を表し、-e は stderr を表します。


awkの代替を試すには、シェルスクリプトを使用できます。シェルがbashであることを確認してください

stdbuf -o 0 -e 0 fdkaac ... 2>&1 | 
(IFS="$IFS%[]"
while read -d$'\r' junk1 percent junk2
do  echo "$percent"
done) |
zenity --progress --title="Title" --text="encoding" --auto-close

追加の3文字 "%[]"を含むようにバスフィールド区切り記号(IFS)を設定すると、実際には入力のスペースのようになります。したがって、read区切り文字キャリッジリターン(-d)を使用すると、行は次のようになります。 1つの単語がvarに入力されます。ゴミ 1、パーセンテージ 2 番目、残りのゴミ 2. 次に、数字だけを保持する必要がある変数をエコーできます。

注:数値フィールドを取得できることを確認するには、zenityビットなしでこれを試してください。パーセントが行の最初のフィールドである必要があるため、最初のvarjunk1を使用する理由がわかりません。ただし、目的の数値が得られない場合は、読み取りからjunk1変数を削除してみてください。

おすすめ記事