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

Ken*_*ici 3 parsing json key environment-variables jq

我正在尝试从JSON输出中解析环境变量docker inspect.令人讨厌的是,这些环境变量不会作为有用的键值对返回.它们只是一个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"
            ]
        }
    }
]
Run Code Online (Sandbox Code Playgroud)

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

{
  "Config": {
    "Env": {
      "JENKINS_HOST": "1.2.3.4",
      "JENKINS_INSTANCE": "tea",
      "JENKINS_NAME": "Enterprise Architecture Tools",
      "JENKINS_VERSION": "2.46.2",
      "JENKINS_PROTOCOL": "http"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

选择数据相对容易,甚至将键和值拆分为单独的元素.例如,如果我使用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"
]
Run Code Online (Sandbox Code Playgroud)

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

pea*_*eak 9

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

{ (.[0]) : .[1] }
Run Code Online (Sandbox Code Playgroud)

所以你要写的东西如下:

 map(.Config.Env |= (map( split("=") | { (.[0]) : .[1] } ) | add))
Run Code Online (Sandbox Code Playgroud)

A2O

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

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

map(.Config.Env |= a2o)
Run Code Online (Sandbox Code Playgroud)

使用matchcapture代替split

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

match("([^=]*)=(.*)") | .captures | {(.[0].string) : .[1].string}
Run Code Online (Sandbox Code Playgroud)

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

[capture( "(?<key>[^:]*):(?<value>.*)" )] | from_entries
Run Code Online (Sandbox Code Playgroud)

index/1

如果您的jq没有正则表达式支持,您可以index/1按照以下方式使用:

index("=") as $ix | {(.[:$ix]) : .[$ix+1:]}
Run Code Online (Sandbox Code Playgroud)