如何解决JQ,两个查询,遍历json的不同部分,将其合并回去
我正在尝试使用jq提取kubeconfig数据。
kubectl config view --raw -o json | jq ...
有一个这样产生的json:
{
"kind": "Config","apiVersion": "v1","preferences": {},"clusters": [
{
"name": "some-name","cluster": {
"server": "https://some-url","certificate-authority-data": "some-cert"
}
},{
"name": "another-name","cluster": {
"server": "https://another-url","certificate-authority-data": "another-cert"
}
}
],"users": [
{
"name": "some-name","user": {
"username": "some-user","password": "some-password"
}
},{
"name": "another-name","user": {
"username": "another-user","password": "another-password"
}
}
],"contexts": [],"current-context": "some-context"
}
问题1: 对于给定的名称“ some-name”,我想提取json:
{
url: "https://some-url",cert: "some-cert",username: "some-user",password: "some-password"
}
问题2: “用户”小节可以采用其他格式
"users": [
{
"name": "...","user": {
"exec": {
...
}
.user.username
或.user.password
或两者都缺失的地方
在这种情况下,即使“集群”查询/分支有结果,整个查询也应返回“ {}”
问题3 ,作为Jeff Mercado回答的后续措施:
我想获得所有集群,并加入(按名称分组)名称:
查看手册https://stedolan.github.io/jq/manual/#Builtinoperatorsandfunctions
“乘法,除法,模:*,/和%”部分,例如:
jq '{"k": {"a": 1,"b": 2}} * {"k": {"a": 0,"c": 3}}' => {"k": {"a": 0,"b": 2,"c": 3}}'
假设“ k”是“名称”的值,则给出正确的结果。因此,按“ k”分组,合并(*)结果。
我产生了以下查询:
echo "${json}" | jq -r '(.clusters[] | {(.name): {url: .cluster.server,cert: .cluster["certificate-authority-data"]}}) * (.users[] | {(.name): {user: .user.username,password: .user.password}})'
第一部分返回{“ name”:{url:cert}},第二部分返回{“ name”:{username,password}} 但是,结果不是像jq Manual中那样合并,而是其他...产品?
{
"some-name": {
"url": "https://some-url","cert": "some-cert","user": "some-user","password": "some-password"
}
}
{
"another-name": {
"url": "https://another-url","cert": "another-cert"
},"some-name": {
"user": "some-user","password": "some-password"
}
}
{
"some-name": {
"url": "https://some-url","cert": "some-cert"
},"another-name": {
"user": "another-user","password": "another-password"
}
}
{
"another-name": {
"url": "https://another-url","cert": "another-cert","user": "another-user","password": "another-password"
}
}
为什么/是什么?关于产品('*')的以下某种想法,但我(很可能是错误地)理解的jq教程却并非如此
实验: 我现在有2个查询会产生部分结果。
让我们抓取原始json(上方)并进行解析:
read -d '' json << EOF
...
EOF
查询:
echo "${json}" | jq -r '.clusters[] | select(.name=="some-name") | .cluster | {url: .server,cert: .["certificate-authority-data"]}' &&\
echo "${json}" | jq -r '.users[] | select(.name=="some-name") | .user | {user: .username,password: .password}'
将产生分割输出:
{
"url": "https://some-url","cert": "some-cert"
}
{
"user": "some-user","password": "some-password"
}
或者,添加密钥以进行进一步合并:
echo "${json}" | jq -r '.clusters[] | select(.name=="some-name") | {name: .name,url: .cluster.server,cert: .cluster["certificate-authority-data"]}' &&\
echo "${json}" | jq -r '.users[] | select(.name=="some-name") | {name: .name,user: .user.username,password: .user.password}'
会产生:
{
"name": "some-name","url": "https://some-url","cert": "some-cert"
}
{
"name": "some-name","password": "some-password"
}
不需要“名称”,但可以用作联接操作
解决方法
因此,您已经知道如何按名称分别获取集群和用户,第一步是在单个过滤器中同时选择它们:
(.clusters[] | select(.name == $name).cluster),(.users[] | select(.name == $name).user)
这将产生两个单独的对象,即群集,然后是用户。但是我们要合并它们。有很多方法可以做到这一点。您可以直接添加它们(+
)或合并它们(*
),但两者之间没有实质区别。您只需要将属性重新映射到所需的名称即可。
(.clusters[] | select(.name == $name).cluster | {url: .server,cert: ."certificate-authority-data"})
+
(.users[] | select(.name == $name).user | {username,password})
将名称作为参数传递给过滤器;
$ kubectl config view --raw -o json | jq --arg name some-name '
(.clusters[] | select(.name == $name).cluster | {url: .server,password})
'
对于问题的第二部分,如果事实证明映射的用户缺少关键属性,而您想忽略它们,则只需在末尾添加另一个select
过滤器以测试这些属性,并替换为空的对象,如果什么也没找到:
... | select(has("username") and has("password")) // {}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。