我有一本关于用户名的字典,例如:
"userinfo": { "alice": { "key1": 1, "key2": 2}, "bob": { "key1": 11, "key2": 22}, ... }
我想显示用户名和一些值的表格文本。
alice 1 2
bob 11 22
将用户名放入第一列或将值拉出()放入后面的列中很容易.info[]|[.key1,.key2]
,但我不知道如何在同一jq
命令中获取用户名及其下的值。我试图避免做一些愚蠢的事情,比如jq
多次运行并粘贴输出。
答案1
答案2
$ jq -r '.userinfo | keys[] as $k | [ $k, .[$k][] ] | @tsv' file
alice 1 2
bob 11 22
这里假设输入的file
是一个有效的 JSON 文档,例如
{
"userinfo": {
"alice": {
"key1": 1,
"key2": 2
},
"bob": {
"key1": 11,
"key2": 22
}
}
}
该jq
表达式挑选出userinfo
顶级对象,然后迭代该对象的键,每个键都分配给内部变量$k
。特别是[]
ofkeys[]
导致循环所有键(用户名)。
对于每次迭代,都会构造数组[ $k, .[$k][] ]
,即由键本身组成的数组,后跟与该特定键关联的对象中的值userinfo
(无论下面的键.[$k]
是什么或可能有多少,即我们忽略键)key1
和key2
他们自己)。
然后将构造的数组传递给@tsv
运算符,将其输出为制表符分隔的记录。
为了使这一点有意义,我们假设 下每个对象的键以相同的方式排序userinfo
。如果情况并非如此,您可能需要jq -S .
首先传递数据来对键进行排序。如果子对象具有不同的键集(有些可能有 akey3
而其他可能缺少key1
),则输出仍然不太可能有意义,因为输出中的字段上没有标头,并且没有迹象表明在一个东西。
name
我们可以使用稍微复杂的表达式,根据子对象中的键名称(并用作用户名字段的标题)为每个字段生成标题jq
:
(
[.userinfo[] | keys[]] | unique
) as $h |
# This creates the header using "name" and the unique keys
# from each sub-object:
[ "name", $h[] ],
# Now we need a "double loop" over each user object and
# the unique keys (in $h) that we extracted previously,
# basically: for each user, create an array consisting of
# the username and the value for each of the keys
# (the inner loop):
[
.userinfo as $u |
$u |
# Outer loop:
keys[] as $k |
[
# The username:
$k,
# Inner loop over the $h array, extracting
# either useful data or nothing depending on
# whether the key exists in this object.
($h[] | $u[$k][.])
]
]
| @tsv
具有未排序和缺失/额外键的示例输入:
{
"userinfo": {
"alice": {
"key2": 2,
"key1": 1
},
"bob": {
"key1": 11,
"key2": 22
},
"mallory": {
"key1": 111,
"key3": 333
}
}
}
输出:
name key1 key2 key3
alice 1 2
bob 11 22
mallory 111 333