有没有办法让 jq 在遇到错误后继续前进?

Is there a way to have jq keep going after it hits an error?

我正在使用 jq 解析日志数据,偶尔日志中包含格式错误的内容(无效 json),发生这种情况时,jq 会在此时中止处理。

有没有办法让 jq 继续处理它可以处理的内容,同时通过 stderr 报告问题?

我知道如果你的 JSON 中有换行符,如果它从下一行开始,jq 可能会遇到麻烦,但在这种情况下,你最终还是会到达你找到开始的地步合法的 json 邮件,可以继续处理。

如果你有 jq 1.5,答案是:,但一般来说,预处理(例如使用 hjson 或 any-json)会更好。

无论如何,这个想法只是利用 try/catch 功能。这是使用 inputs 过滤器的示例。请注意,通常应使用 -n 选项调用 jq 才能使其正常工作。

recover.jq

def handle: inputs | [., "length is \(length)"] ;
def process: try handle catch ("Failed", process) ;
process

bad.json

[1,2,3]
{id=546456, userId=345345}
[4,5,6]

见jq 运行:

$ jq -n -f recover.jq bad.json
[
  "[1,2,3]",
  "length is 3"
]
"Failed"
[
  "[4,5,6]",
  "length is 3"
]

使用 jq-1.5 我可以做到以下几点:

使用此示例文件:

cat << EOF > example.log
{"a": 1}
{invalid
{"b": 2}
EOF

将非 json 行输出为不带引号的字符串:

cat example.log | jq --raw-input --raw-output '. as $raw | try fromjson catch $raw'

{
  "a": 1
}
{invalid
{
  "b": 2
}

静默跳过非json行:

cat example.log | jq --raw-input 'fromjson?'

{
  "a": 1
}
{
  "b": 2
}

如果整个输入预计是单个多行 json blob,您可以添加 --slurp

示例文件:

cat << EOF > valid-multiline.log
{
  "a": 1,
  "b": 2
}
EOF

cat << EOF > invalid-multiline.log
{
  asdf
  "b": 2
}
EOF

产出

cat valid-multiline.log | jq --slurp --raw-input --raw-output '. as $raw | try fromjson catch $raw'

{
  "a": 1,
  "b": 2
}

cat invalid-multiline.log | jq --slurp --raw-input --raw-output '. as $raw | try fromjson catch $raw'

{
  asdf
  "b": 2
}