繁体   English   中英

使用jq将x = y对转换为键/值对

[英]Use jq to turn x=y pairs into key/value pairs

我正在尝试从docker inspect的JSON输出中解析环境变量。 令人讨厌的是,这些环境变量不会作为有用的键值对返回。 它们只是一个x = y字符串的数组。 这是输出的相关片段:

[
    {
        "Config": {
            "Env": [
                "JENKINS_HOST=1.2.3.4",
                "JENKINS_INSTANCE=tea",
                "JENKINS_NAME=Enterprise Architecture Tools",
                "JENKINS_VERSION=2.46.2",
                "JENKINS_PROTOCOL=http"
            ]
        }
    }
]

我想将该数组转换为这样的:

{
  "Config": {
    "Env": {
      "JENKINS_HOST": "1.2.3.4",
      "JENKINS_INSTANCE": "tea",
      "JENKINS_NAME": "Enterprise Architecture Tools",
      "JENKINS_VERSION": "2.46.2",
      "JENKINS_PROTOCOL": "http"
    }
  }
}

这样,我可以使用像jq '.[] | .Config.Env.JENKINS_HOST'这样的命令 jq '.[] | .Config.Env.JENKINS_HOST'获取我关心的值。 我无法弄清楚如何实现这一目标。

选择数据相对容易,甚至将键和值拆分为单独的元素。 例如,如果我使用jq '.[] | .Config.Env | .[] | split("=")' jq '.[] | .Config.Env | .[] | split("=")' jq '.[] | .Config.Env | .[] | split("=")' ,我得到这样的数据:

[
  "JENKINS_HOST",
  "1.2.3.4"
]
[
  "JENKINS_INSTANCE",
  "tea"
]
[
  "JENKINS_NAME",
  "Enterprise Architecture Tools"
]
[
  "JENKINS_VERSION",
  "2.46.2"
]
[
  "JENKINS_PROTOCOL",
  "http"
]

但是,我无法弄清楚如何将该数据转换为对象分配。 它似乎应该是mapreduce某种组合,但我很难过。 谁能指出我正确的方向?

要将两个字符串的数组(例如[“k”,“v”])转换为对象,您可以编写:

{ (.[0]) : .[1] }

所以你要写的东西如下:

 map(.Config.Env |= (map( split("=") | { (.[0]) : .[1] } ) | add))

A2O

抽象出数组到对象的功能使得解决方案更易于理解:

def a2o: map( split("=") | { (.[0]) : .[1] } ) | add;

map(.Config.Env |= a2o)

使用matchcapture而不是split

由于“=”字符可能出现在每个var=value字符串的“value”部分中,因此使用split naively可能不是一个好主意。 假设您的jq支持正则表达式,这是一个更强大的替代方案:

match("([^=]*)=(.*)") | .captures | {(.[0].string) : .[1].string}

或者,更简洁,也许更优雅:

[capture( "(?<key>[^:]*):(?<value>.*)" )] | from_entries

index/1

如果你的jq没有正则表达式支持,你可以使用index/1 ,沿着这些方向:

index("=") as $ix | {(.[:$ix]) : .[$ix+1:]}

鉴于要转换为单个对象的项目集合,我通常会选择使用reduce来实现此目的。 将这些项目转换为其组成键和值,然后分配给结果对象。

reduce (.[] | split("=")) as [$key, $value] ({}; .[$key] = $value)

虽然在这里使用from_entries也很有用,但是你要创建一个它期望的键/值对象的数组。

map(split("=") as [$key, $value] | {$key, $value}) | from_entries

然后使用您选择的任何方法将所有内容与Env属性的更新放在一起。

.[].Config.Env |= reduce (.[] | split("=")) as [$key, $value] ({}; .[$key] = $value)
#or
.[].Config.Env |= (map(split("=") as [$key, $value] | {$key, $value}) | from_entries)

https://jqplay.org/s/qfItW5U-Tf

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM