0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

jq コマンドで入力に JSON 形式でない行が含まれる場合にそれを取り除く

Last updated at Posted at 2025-01-30

問題

以下のログファイルから JSON 形式の行を jq コマンドで処理したい。

sample.log
hoge
{"time":"2024-01-01T00:00:00.000000+09:00","level":"INFO","request_id":"aaa","message":"👼"}
fuga
{"time":"2024-01-01T23:59:59.999999+09:00","level":"ERROR","request_id":"bbb","message":"👿"}
{"time":"2024-01-31T00:00:00.000000+09:00","level":"ERROR","request_id":"ccc","message":"😈"}
foo

例えば "level":"ERROR" の行のみを取得したい。しかし JSON 形式ではない行のせいでパースエラーが発生してしまう 😢

$ cat sample.log | jq -c 'select(.level == "ERROR")'
jq: parse error: Invalid numeric literal at line 2, column 0

例えば grep コマンドでJSON 形式ではない行を取り除くことでエラーを防ぐことができる。

$ cat sample.log | grep '^{.*}$' | jq -c 'select(.level == "ERROR")'
{"time":"2024-01-01T23:59:59.999999+09:00","level":"ERROR","request_id":"bbb","message":"👿"}
{"time":"2024-01-31T00:00:00.000000+09:00","level":"ERROR","request_id":"ccc","message":"😈"}

もっといい方法、具体的には jq コマンドだけでエラーを防ぐ方法はないだろうか? 🤔

解決方法

jq コマンドの -R オプションと fromjson? を利用する。

$ cat sample.log | jq -cR 'fromjson? | select(.level == "ERROR")'
{"time":"2024-01-01T23:59:59.999999+09:00","level":"ERROR","request_id":"bbb","message":"👿"}
{"time":"2024-01-31T00:00:00.000000+09:00","level":"ERROR","request_id":"ccc","message":"😈"}
  • -R
    • 入力を生の文字列として読み込む
    • 通常、jq は入力を JSON として解析するが、-R オプションを使用すると、入力をそのまま文字列として扱う
  • fromjson?
    • 各行を JSON として解析する
    • ? は解析に失敗した場合、エラーを無視して null を返すことを表す

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?