使用jq将x = y对转换成键/值对 [英] Use jq to turn x=y pairs into key/value pairs

查看:160
本文介绍了使用jq将x = y对转换成键/值对的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  [
{
配置:{
Env:[
JENKINS_HOST = 1.2.3.4,
JENKINS_INSTANCE =茶,
JENKINS_NAME =企业架构工具,
JENKINS_VERSION = 2.46.2,
JENKINS_PROTOCOL = http
]
}
}
]
/ pre>

我想将该数组转换成如下所示:

JENKINS_NAME:企业架构工具,
JENKINS_VERSION:2.46.2,
JENKINS_PROTOCOL:http
}
}
}

这样,我可以使用像 jq'。[] | .Config.Env.JENKINS_HOST'以获取我关心的值。我不知道如何完成这个。



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

  [
JENKINS_HOST,
1.2.3.4
]
[
JENKINS_INSTANCE,
tea
]
[
JENKINS_NAME,
企业架构工具
]
[
JENKINS_VERSION,
2.46.2
]
[
JENKINS_PROTOCOL,
http
]

但是,我无法弄清楚如何将数据转换为对象分配。似乎它应该是 map reduce 的组合,但我被困住了。任何人都可以指向正确的方向?

解决方案

要转换两个字符串的数组(例如[k,v ])到一个对象,你可以写:

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

所以你想写一些如下的东西:

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



a2o



抽出数组到对象功能使解决方案更易消化:

  def a2o:map(split(=)| {(。[0 ]):。[1]})|加; 

地图(.Config.Env | = a2o)



使用 match capture 而不是 split



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

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

或者稍微多一些简洁而又优雅地:

  [capture((?< key> [^:] *)值>。*))] | from_entries 



index / 1



如果您的jq没有正则表达式支持,可以使用 index / 1 ,这些行:

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


I'm trying to parse environment variables from the JSON output of docker inspect. Annoyingly, those environment variables aren't returned as useful key-value pairs. They're just an array of x=y strings. Here's a relevant snippet of the output:

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

I would like to convert that array into something like this:

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

That way, I can use a command like jq '.[] | .Config.Env.JENKINS_HOST' to get the values that I care about. I can't figure out how to accomplish this.

It's relatively easy to select the data and even split the key and value into separate elements. For instance, if I use jq '.[] | .Config.Env | .[] | split("=")', I get data like this:

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

However, I can't figure out how to turn that data into an object assignment. It seems like it should probably be some combination of map or reduce, but I'm stumped. Can anyone point me in the right direction?

解决方案

To convert an array of two strings (e.g. ["k", "v"]) to an object, you can write:

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

So you'll want to write something like:

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

a2o

Abstracting out the array-to-object functionality makes the solution a bit more digestible:

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

map(.Config.Env |= a2o)

Using match or capture instead of split

Since it is possible for an "=" character to appear in the "value" part of each var=value string, using split naively might not be such a great idea. Here is a more robust alternative, assuming your jq supports regular expressions:

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

Or, slightly more succinctly and perhaps elegantly:

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

index/1

If your jq does not have regex support, you could use index/1, along these lines:

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

这篇关于使用jq将x = y对转换成键/值对的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆