获取 jq json 解析中的第一个(或第 n 个)元素
get the first (or n'th) element in a jq json parsing
我可以在 []
中获取 json 中的第一个元素
$ echo '[{"a":"x", "b":true}, {"a":"XML", "b":false}]' | jq '.[1]'
{
"a": "XML",
"b": false
}
但是如果 json 已经反汇编了(例如,在使用 'select' 过滤条目之后),我怎样才能选择单个条目并避免这里看到的错误?
$ echo '[{"a":"x", "b":true}, {"a":"x", "b":false},{"a":"XML", "b":false}]' | jq '.[] | select( .a == "x")'
{
"a": "x",
"b": true
}
{
"a": "x",
"b": false
}
$ echo '[{"a":"x", "b":true}, {"a":"x", "b":false},{"a":"XML", "b":false}]' | jq '.[] | select( .a == "x") | .[1]'
jq: error (at <stdin>:1): Cannot index object with number
使用map
cat raw.json|jq -r -c 'map(select(.a=="x"))|.[1]'
map
接收一个 filter 来过滤数组。
这个命令
cat raw.json|jq -r -c 'map(select(.a=="x"))'
给出中间结果
[{"a":"x","b":true},{"a":"x","b":false}]
.[1]
取第一个元素
您可以将 select
的结果包装在一个数组中:
jq '[.[]|select(.a=="x")][0]' your.json
输出:
{
"a": "x",
"b": false
}
jq 还提供 first/0
, last/0
, nth/1
所以在这种情况下过滤器
( map(select(.a == "x")) | first )
, ( map(select(.a == "x")) | last )
, ( map(select(.a == "x")) | nth(1) )
产生
{
"a": "x",
"b": true
}
{
"a": "x",
"b": false
}
{
"a": "x",
"b": false
}
其他流媒体形式 'first/1', 'last/1' and 'nth/2' 也可以使用此数据
( first(.[] | select(.a == "x")) )
, ( last(.[] | select(.a == "x")) )
, ( nth(1; .[] | select(.a == "x")) )
产生
{
"a": "x",
"b": true
}
{
"a": "x",
"b": false
}
{
"a": "x",
"b": false
}
之前的许多答案都是通过避免首先创建对象流来实现的。但是,如果您 开始 对象流,例如 JSON 格式的应用程序日志,该怎么办?如果您的输入文件(或流)中有多个对象,从独立对象流中选择一个条目所需要做的就是使用 --slurp
选项(或简称 -s
表格):
o --slurp/-s:
Instead of running the filter for each JSON object in the input, read
the entire input stream into a large array and run the filter just once.
然后你就可以索引到数组中了。例如,要获取第二项(索引为 1):
jq --slurp '.[1]'
将此与您的原始问题放在一起,您希望 select 来自流的项目:
echo '{"a":"x", "b":true} {"a":"XML", "b":false}' | jq --slurp '.[1]'
导致此输出:
{
"a": "XML",
"b": false
}
我可以在 []
中获取 json 中的第一个元素$ echo '[{"a":"x", "b":true}, {"a":"XML", "b":false}]' | jq '.[1]'
{
"a": "XML",
"b": false
}
但是如果 json 已经反汇编了(例如,在使用 'select' 过滤条目之后),我怎样才能选择单个条目并避免这里看到的错误?
$ echo '[{"a":"x", "b":true}, {"a":"x", "b":false},{"a":"XML", "b":false}]' | jq '.[] | select( .a == "x")'
{
"a": "x",
"b": true
}
{
"a": "x",
"b": false
}
$ echo '[{"a":"x", "b":true}, {"a":"x", "b":false},{"a":"XML", "b":false}]' | jq '.[] | select( .a == "x") | .[1]'
jq: error (at <stdin>:1): Cannot index object with number
使用map
cat raw.json|jq -r -c 'map(select(.a=="x"))|.[1]'
map
接收一个 filter 来过滤数组。
这个命令
cat raw.json|jq -r -c 'map(select(.a=="x"))'
给出中间结果
[{"a":"x","b":true},{"a":"x","b":false}]
.[1]
取第一个元素
您可以将 select
的结果包装在一个数组中:
jq '[.[]|select(.a=="x")][0]' your.json
输出:
{
"a": "x",
"b": false
}
jq 还提供 first/0
, last/0
, nth/1
所以在这种情况下过滤器
( map(select(.a == "x")) | first )
, ( map(select(.a == "x")) | last )
, ( map(select(.a == "x")) | nth(1) )
产生
{
"a": "x",
"b": true
}
{
"a": "x",
"b": false
}
{
"a": "x",
"b": false
}
其他流媒体形式 'first/1', 'last/1' and 'nth/2' 也可以使用此数据
( first(.[] | select(.a == "x")) )
, ( last(.[] | select(.a == "x")) )
, ( nth(1; .[] | select(.a == "x")) )
产生
{
"a": "x",
"b": true
}
{
"a": "x",
"b": false
}
{
"a": "x",
"b": false
}
之前的许多答案都是通过避免首先创建对象流来实现的。但是,如果您 开始 对象流,例如 JSON 格式的应用程序日志,该怎么办?如果您的输入文件(或流)中有多个对象,从独立对象流中选择一个条目所需要做的就是使用 --slurp
选项(或简称 -s
表格):
o --slurp/-s: Instead of running the filter for each JSON object in the input, read the entire input stream into a large array and run the filter just once.
然后你就可以索引到数组中了。例如,要获取第二项(索引为 1):
jq --slurp '.[1]'
将此与您的原始问题放在一起,您希望 select 来自流的项目:
echo '{"a":"x", "b":true} {"a":"XML", "b":false}' | jq --slurp '.[1]'
导致此输出:
{
"a": "XML",
"b": false
}