パイプラインチェーンでjqを使用すると、出力は生成されません。

パイプラインチェーンでjqを使用すると、出力は生成されません。

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_subIoTを通じて発見したとおり(ここで問題を発見しました)尾を包むことです。そしてシェルスクリプトの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

これはjqHomebrewを介してインストールされた最新バージョンです。

$ 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便利です)。

おすすめ記事