我和jbyler有相同的情况 - 我想解析N行JSON日志,其中每行都是一个单独的对象:
host ~
{"remote_addr":"127.0.0.1","remote_port":"47700","time_iso8601":"2022-08-31T00:0
{"remote_addr":"127.0.0.1","remote_port":"35576","time_iso8601":"2022-08-31T00:0
{"remote_addr":"127.0.0.1","remote_port":"47708","time_iso8601":"2022-08-31T00:0
{"remote_addr":"127.0.0.1","remote_port":"52974","time_iso8601":"2022-08-31T00:0
{"remote_addr":"127.0.0.1","remote_port":"52976","time_iso8601":"2022-08-31T00:0
{"remote_addr":"127.0.0.1","remote_port":"51414","time_iso8601":"2022-08-31T00:0
{"remote_addr":"127.0.0.1","remote_port":"41942","time_iso8601":"2022-08-31T00:1
{"remote_addr":"127.0.0.1","remote_port":"41946","time_iso8601":"2022-08-31T00:1
{"remote_addr":"127.0.0.1","remote_port":"37982","time_iso8601":"2022-08-31T00:1
{"remote_addr":"127.0.0.1","remote_port":"56602","time_iso8601":"2022-08-31T00:1
我不喜欢使用--slurp
解决方案,因为这会导致jq
读取整个文件,而我可能只对前N行感兴趣。
解决方案似乎是将input
函数与jq -n
结合使用,它可以读取单个输入对象:
host ~
127.0.0.1 47700 2022-08-31T00:02:53+02:00
结合
range
,我可以使用它来读取最多N个输入对象。
host ~ # cat /var/log/nginx/access.log.json | jq -r -n 'range(10) as $i | input | [.remote_addr, .remote_port, .time_iso8601] | @tsv'
127.0.0.1 47700 2022-08-31T00:02:53+02:00
127.0.0.1 35576 2022-08-31T00:02:53+02:00
127.0.0.1 47708 2022-08-31T00:02:53+02:00
127.0.0.1 52974 2022-08-31T00:07:53+02:00
127.0.0.1 52976 2022-08-31T00:07:53+02:00
127.0.0.1 51414 2022-08-31T00:07:58+02:00
127.0.0.1 41942 2022-08-31T00:12:53+02:00
127.0.0.1 41946 2022-08-31T00:12:53+02:00
127.0.0.1 37982 2022-08-31T00:13:03+02:00
127.0.0.1 56602 2022-08-31T00:17:53+02:00
但是要小心将其包装成数组 - 如果做错了,会导致jq
重新评估[range(10) as $i | input]
表达式,所以这里我得到的不是元素[0, 1, 2]
,而是[0, 11, 22]
:
# WRONG, DON'T DO THIS
host ~ # cat /var/log/nginx/access.log.json | jq -r -n '[range(10) as $i | input][0,1,2] | [.remote_addr, .remote_port, .time_iso8601] | @tsv'
127.0.0.1 47700 2022-08-31T00:02:53+02:00
127.0.0.1 59784 2022-08-31T00:18:22+02:00
127.0.0.1 34316 2022-08-31T00:37:53+02:00
为了安全地多次访问同一数组,您需要在它们之间使用管道:
host ~ # cat /var/log/nginx/access.log.json | jq -r -n '[range(10) as $i | input] | .[0,1,2] | [.remote_addr, .remote_port, .time_iso8601] | @tsv'
127.0.0.1 47700 2022-08-31T00:02:53+02:00
127.0.0.1 35576 2022-08-31T00:02:53+02:00
127.0.0.1 47708 2022-08-31T00:02:53+02:00
通过这种方式,您可以从输入文件中获取最多N个对象,然后从此选择中提取任意对象。
'.[1]'
实际上获取第二个元素。'.[0]'
将获取第一个元素。Javascript的数组是以零为基础的。 - Tony