jq
出力をリダイレクトする際の明示的なフィルタの必要性について、Web全体で議論がありました。ただし、jq
パイプラインチェーンの一部である場合は、明示的なフィルタを使用しても出力をリダイレクトできません。
考慮する:
touch in.txt
tail -f in.txt | jq '.f1'
# in a different terminal:
echo '{"f1":1,"f2":2}' >> in.txt
echo '{"f1":3,"f2":2}' >> in.txt
予想通り、コマンドの生端末出力は次jq
のようになります。
1
3
ただし、コマンドの最後にリダイレクトまたはパイプを追加すると、jq
出力は自動的に保持されます。
rm in.txt
touch in.txt
tail -f in.txt | jq '.f1' | tee out.txt
# in a different terminal:
echo '{"f1":1,"f2":2}' >> in.txt
echo '{"f1":3,"f2":2}' >> in.txt
最初の端末には出力が表示されず、out.txtは空です。
何百ものバリエーションを試しましたが、これは理解しにくい問題です。ただ私が見つけた解決策、mosquitto_sub
IoTを通じて発見したとおり(ここで問題を発見しました)尾を包むことです。そしてシェルスクリプトのjq関数:
#!/bin/bash
tail -f $1 | while IFS='' read line; do
echo $line | jq '.f1'
done
それから:
./tail_and_jq.sh | tee out.txt
# in a different terminal:
echo '{"f1":1,"f2":2}' >> in.txt
echo '{"f1":3,"f2":2}' >> in.txt
もちろん、結果は次のようになります。
1
3
これはjq
Homebrewを介してインストールされた最新バージョンです。
$ echo $SHELL
/bin/bash
$ jq --version
jq-1.5
$ brew install jq
Warning: jq 1.5_3 is already installed and up-to-date
jq
これはパイプラインチェーンを理解する際の(ほとんど文書化されていない)エラーですか?
ベストアンサー1
jq
標準出力が端末でない場合、その出力はバッファリングされます。
jq
各オブジェクトの出力バッファを後でフラッシュするように要求するには、--unbuffered
そのオプションを使用します。
tail -f in.txt | jq --unbuffered '.f1' | tee out.txt
jq
マニュアルから:
--unbuffered
各JSONオブジェクトを印刷してから出力をフラッシュします(遅いデータソースを別の場所にパイプして出力を
jq
パイプする場合にjq
便利です)。