我正在解析看起来像这样的弹性日志
$ 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
,我又得到了每条消息的列表。
我无法使用 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"
您可以在此在线演示中进行测试。
在形成数组时进行选择的有效方法是将
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; .)[]
如果您希望数组被分散,只需附加
[]
。
jq -c 'select(."level" != "INFO")|减少输入为 $i ([.];.+[$i])' my_log_file.txt