jq - 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
两者都可能丢失
在这种情况下,整体查询应该返回“{}”,即使“clusters”查询/分支有结果
问题 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”是“name”的值,给出大概正确的结果。因此,按“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 手册中那样合并,而是其他东西......产品?
{
"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",
"user": "some-user",
"password": "some-password"
}
"name" 不是必需的,但可以用作连接操作
解决方案
因此,您已经知道如何分别按名称获取集群和用户,第一步是在单个过滤器中选择它们:
(.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, cert: ."certificate-authority-data"})
+
(.users[] | select(.name == $name).user | {username, password})
'
对于您问题的第二部分,如果事实证明映射的用户缺少关键属性并且您想省略它们,只需select
在末尾添加另一个过滤器以测试这些属性并在未找到任何内容时替换为空对象:
... | select(has("username") and has("password")) // {}
推荐阅读
- reactjs - 如何使用 create-react-app 登录到服务器端控制台?
- java - 从另一个 Jenkins 构建中查找工件 URL
- javascript - MongoDB 触发器文件中的代码是 Producing a Customer.findOne() is not a function 错误
- gradle - 使用 gradle java pugin 构建类包结构不一致
- angular - 如何使用 Material Angular Sort 对多个表格进行排序?
- javascript - 从不同的 Spotfire 服务器动态加载不同的 Spotfire 报告
- android - 如何将原始日期字符串转换为年龄?
- nginx - Nginx - 基于 ISP 的不同代理通行证
- html - 网站强制用户快速重复点击返回按钮返回
- android - 一键实现两种方法