我可以根据列表中的值输出布尔值吗



编辑:我使用@peak提供的解决方案来执行以下操作:

$ jq -r --argjson whitelist '["role1", "role2"]' '
select(has("roles") and any(.roles[]; . == "role1" or . == "role2"))
| (reduce ."roles"[] as $r ({}; .[$r]=true)) as $roles
| [.email, .username, .given_name, .family_name, ($roles[$whitelist[]]
| . != null)]
| @csv
' users.json

添加了select(),以筛选出尚未加入且没有任何角色的用户,并确保输出中包含的用户至少具有一个目标角色。

场景:用户配置文件为JSON文档,其中每个配置文件都有一个列表对象及其分配的角色。示例:

{
"username": "janedoe",
"roles": [
"role1",
"role4",
"role5"
]
}

实际的数据文件是一个ndjson文件,每行一个用户对象。

我只对特定的角色感兴趣,比如role1role3role4。我想生成一个CSV格式为:

username,role1?,role3?,role4?

例如

janedoe,true,false,true

我还没有弄清楚的部分是如何输出布尔值或Y/N来响应列表对象中的值。这是我在jq中可以做的事情吗?

使用您的输入,调用:

jq -r --argjson whitelist '["role1", "role3", "role4"]' '
(["username"] + $whitelist),
[.username, ($whitelist[] as $w | .roles | index([$w]) != null)]
| @csv
'

生产:

"username","role1","role3","role4"
"janedoe",true,false,true

注意事项:

  1. 上面jq滤波器的倒数第二行可以缩短为:

    [.username, (.roles | index($whitelist[]) != null)]

  2. 假设有不止一个用户,您只需要标题行一次,在这种情况下,上面的解决方案需要调整。

使用IN/1

因为CCD_ 7并不像它可能的那样高效,你可能会考虑这个替代方案:

(["username"] + $whitelist),
(.roles as $roles | [.username, ($whitelist[] | IN($roles[]) )])
| @csv

使用JSON字典

如果角色数量很大,那么可能会更多高效构建JSON字典以避免重复的线性查找:

(reduce .roles[] as $r ({}; .[$r]=true)) as $roles
| (["username"] + $whitelist),
[.username, ($roles[$whitelist[]] != null)]
| @csv

以ndjson作为输入

为了提高效率,并确保只有一个标头,可以将inputs与-n命令行选项一起使用。添加修改后的Q中提到的额外字段,您可能会得到:

jq -nr --argjson whitelist '["role1", "role2"]' '
["email", "username", "given_name", "family_name"] as $greenlist
| ($greenlist + $whitelist),
(inputs 
| select(has("roles") and any(.roles[] == $whitelist[]; true))
| (reduce ."roles"[] as $r ({}; .[$r]=true)) as $roles
| [ .[$greenlist[]], ($roles[$whitelist[]] != null) ])
| @csv
' users.json

最新更新