jq:如何slurp mid-filter(将单独的json对象转换为数组)

问题描述 投票:0回答:3

我正在解析看起来像这样的弹性日志

$ cat my_log_file.txt:
{"level": "INFO", "message": "foo"}
{"level": "WARN", "message": "bar"}
{"level": "WARN", "message": "baz"}

因为它们每行一个,以前我使用

jq -s
将它们放入一个实际的数组中,我可以在上面运行
map

jq -s 'map(.message) | unique' my_log_file.txt

现在我只想选择具有 level != "INFO" 的行。我应该能够只使用这个食谱,但是再次

jq
遇到了麻烦,每行都是一个单独的对象而不是在数组中。

我无法使用 slurp,因为它不适用于此命令:

jq 'select(."level" != "INFO")' my_log_file.txt

但是当我想再次映射到 .message 时,我得到了之前没有使用 slurp 时遇到的相同错误:

$ jq 'select(."level" != "INFO") | map(.message) | unique' my_log_file.txt
jq: error (at <stdin>:90): Cannot index string with string "message"

如何在中途转换我的记录——选择完成后,转换结果

{"level": "WARN", "message": "bar"}
{"level": "WARN", "message": "bar"}

[
  {"level": "WARN", "message": "bar"},
  {"level": "WARN", "message": "bar"}
]

我听说

inputs
是为了取代slurp而设计的,但是当我尝试时

$ jq 'select(."level" != "INFO") | [inputs]' my_log_file.txt

忽略了我的

select
,我又得到了每条消息的列表。

jq
3个回答
1
投票

我无法使用 slurp,因为它不适用于此命令

如果您使用 slurp,则需要将

select
包裹在
map()
中才能使其正常工作:

jq -s 'map(select(.level != "INFO"))' my_log_file.txt

因此,要获得所有独特的

message
,其中
level != "INFO"
,您可以使用:

jq -s 'map(select(.level != "INFO").message) | unique[]' my_log_file.txt

将会输出:

"bar"
"baz"

您可以在此在线演示中进行测试。


1
投票

在形成数组时进行选择的有效方法是将

inputs
与 -n 命令行选项一起使用,如下所示:

jq -n '[inputs | select(."level" != "INFO") ]' my_log_file.txt

所以您的查询可能是:

[inputs | select(."level" != "INFO") | .message] | unique

或者避免调用

sort
所带来的
unique
并假设所有 .message 值都是字符串:

INDEX(inputs | select(.level != "INFO"); .message)
| keys_unsorted

或者更好:

INDEX(inputs | select(.level != "INFO") | .message; .)[]

如果您希望数组被分散,只需附加

[]


0
投票

jq -c 'select(."level" != "INFO")|减少输入为 $i ([.];.+[$i])' my_log_file.txt

© www.soinside.com 2019 - 2024. All rights reserved.