jq 添加额外的变量前缀

jq add additional variable prefix

我最近问了几个 jq 配对问题,并且有了所有完美的答案,我确实学到了很多东西。我希望这个问题仍然是可能的..

{
   "kind":"ServiceList",
   "apiVersion":"v1",
   "items":[
      {
         "spec":{
            "ports":[
               {
                  "name":"https",
                  "protocol":"TCP",
                  "port":443,
                  "targetPort":6443
               },
                              {
                  "name":"http",
                  "protocol":"TCP",
                  "port":80,
                  "targetPort":8080
               }
            ],
            "clusterIP":"10.233.0.1",
            "type":"ClusterIP",
            "sessionAffinity":"None"
         },
         "status":{
            "loadBalancer":{
               
            }
         }
      },
      {
         "spec":{
            "ports":[
               {
                  "protocol":"TCP",
                  "port":80,
                  "targetPort":80,
                  "nodePort":40001
               }
            ],
            "selector":{
               "run":"my-httpd"
            },
            "clusterIP":"10.233.27.102",
            "type":"NodePort",
            "sessionAffinity":"None",
            "externalTrafficPolicy":"Cluster"
         },
         "status":{
            "loadBalancer":{
               
            }
         }
      }
   ]
}

期望的输出是:

port01name=https;port01protocol=TCP;port01port=443;port01targetPort=6443;port02name=http;port02protocol=TCP;port02port=80;port02targetPort=8080
port01protocol=TCP;port01port=80;port01targetPort=80;port01nodePort=40001

它基本上将每个项目的多个端口连接成一行,并将额外的端口{n}作为前缀。

在jq里还能做吗?

或者,输出可以在下面,然后我尝试操作它。

portname=https;portprotocol=TCP;portport=443;porttargetPort=6443;portname=http;portprotocol=TCP;portport=80;porttargetPort=8080
portprotocol=TCP;portport=80;porttargetPort=80;portnodePort=400

在您的引导下,让我们开始:

.items[] .spec.ports[] | to_entries | map("port01\(.key)=\(.value)") | join(";")

关于第一组要求,这有两个问题:

a) 它产生三个独立的字符串; b) “port01”硬连接到前缀中。

第一个问题可以通过将相关子表达式括在方括号中,然后再次使用 join(";") 来解决。

要解决第二个问题,有一个插入前导零的辅助函数会有所帮助。以下内容就足够了:

def leadingZeros($n): tostring | "0"*($n - length) + .;

现在可以根据第一组需求用这个来解决问题:

.items[].spec
| [.ports
   | range(0;length) as $ix
   | .[$ix]
   | to_entries
   | map("port\($ix+1|leadingZeros(2))\(.key)=\(.value)")
   | join(";") ]
| join(";")

全球指数

如果要求修改为要求端口索引是全局的,我们可以采用以下变体:

def addIndex(stream): foreach stream as $x (0; .+1; [., $x]);

addIndex(.items[].spec.ports[])
  | (.[0]|leadingZeros(2)) as $ix
  | .[1]
  | to_entries
  | map("port\($ix)\(.key)=\(.value)")
  | join(";") 

使用 -r command-line 选项,每个端口生成一行:

port01name=https;port01protocol=TCP;port01port=443;port01targetPort=6443
port02name=http;port02protocol=TCP;port02port=80;port02targetPort=8080
port03protocol=TCP;port03port=80;port03targetPort=80;port03nodePort=40001