shell yq,在json值上添加单引号

oknwwptz  于 2023-02-24  发布在  Shell
关注(0)|答案(1)|浏览(215)

我有一个包含以下JSON字符串的shell变量:

echo "${user_part}"

{
  "exec": {
    "apiVersion": "client.authentication.k8s.io/v1beta1",
    "args": [
      "-c",
      "'sops --decrypt ${tokens_file} | jq -cM ''{\"kind\": \"ExecCredential\", \"apiVersion\": \"client.authentication.k8s.io/v1beta1\", \"spec\": {}, \"status\" : {\"token\":.tokens[$ENV.context]}}'''"
    ],
    "command": "bash",
    "env": [
      {
        "name": "context",
        "value": "utility"
      },
      {
        "name": "tokens_file",
        "value": "\"/home/some-user/.kube/tokens with space in name.enc.json\""
      }
    ]
  }
}

应用yq后,我得到了:

echo "${user_part}" | yq --prettyPrint

exec:
  apiVersion: client.authentication.k8s.io/v1beta1
  args:
    - -c
    - '''sops --decrypt ${tokens_file} | jq -cM ''''{"kind": "ExecCredential", "apiVersion": "client.authentication.k8s.io/v1beta1", "spec": {}, "status" : {"token":.tokens[$ENV.context]}}'''''''
  command: bash
  env:
    - name: context
      value: utility
    - name: tokens_file
      value: '"/home/some-user/.kube/tokens with space in name.enc.json"'

预期结果:

exec:
  apiVersion: client.authentication.k8s.io/v1beta1
  args:
    - -c
    - 'sops --decrypt ${tokens_file} | jq -cM ''{"kind": "ExecCredential", "apiVersion": "client.authentication.k8s.io/v1beta1", "spec": {}, "status" : {"token":.tokens[$ENV.context]}}'''
  command: bash
  env:
    - name: context
      value: utility
    - name: tokens_file
      value: "/home/some-user/.kube/tokens with space in name.enc.json"

因此,值按原样传递,不加单引号:

  • .exec.args[1]
  • .exec.env[1].value

完全符合json中的内容。
如何完全关闭这个单引号转义,而不通过yq指定特定元素的自定义转换?
删除第二种情况下的转义双引号,使字符串完全不被YQ引用:
"value": "/home/some-user/.kube/tokens with space in name.enc.json" =〉value: /home/some-user/.kube/tokens with space in name.enc.json,这不是所需要的
根据评论添加:
这些都是“synthetic”kubectl配置文件的一部分。
我已经手动制作了第一个版本:

users:
  - name: utility
    user:
      exec:
        apiVersion: client.authentication.k8s.io/v1beta1
        args: ["-c", "sops --decrypt ${tokens_file} | jq -cM '{\"kind\": \"ExecCredential\", \"apiVersion\": \"client.authentication.k8s.io/v1beta1\", \"spec\": {}, \"status\" : {\"token\":.tokens[$ENV.context]}}'"]
        command: bash
        env:
          - name: context
            value: "utility"
          - name: tokens_file
            value: "/home/some-user/.kube/tokens with space in name.enc.json"

它运行良好,“所需”部分中的片段也是如此
在最初的单引号示例中,是我更改上下文或名称空间(Kubernetes)后kubectl更新的片段,也是kubectl重新处理的yaml文件
我认为这个由kubectl生成和使用的单引号版本更有吸引力,因此没有内部json引号在内单引号中转义。
多引号时,“past-yq”错误输出:

kubectl get namespace
bash: line 1: sops --decrypt ${tokens_file} | jq -cM {"kind": "ExecCredential", "apiVersion": "client.authentication.k8s.io/v1beta1", "spec": {}, "status" : {"token":.tokens[$ENV.context]}}: No such file or directory
Unable to connect to the server: getting credentials: exec: executable bash failed with exit code 127

将引号删除到“所需”状态会使其工作,因此我将其用作成功标准

nc1teljy

nc1teljy1#

这里的问题远远超出了到YAML的转换:原始输入JSON文档本身已损坏。
如果修复了这个问题,就可以直接使用它,而根本不需要任何转换,因为所有有效的JSON也都是有效的YAML;而且您还将确保任何转换为常规格式的YAML的输出在含义上(如果不是语法选择的话)与实际需要的文档相同。

  • 当您在bash中使用双单引号时(无论是在无引号的上下文中还是在单引号的上下文中),它们会相互抵消;bash中的''foo''foo完全相同。
  • 当你在作为-c传递的参数的前后加上单引号时,你向shell指定了整个命令是一个单词(也就是一个可执行文件的名称),这显然是不正确的,而且会导致command not found错误。
  • 如果扩展$tokens_file时没有在扩展前后加上 * syntatic * 引号(要符合语法,引号必须在shell语言源代码中,而不是在变量的值中!),则该变量将被单词拆分为单独的值。
  • 您的环境变量在.kube标记的值中有 literal 引号,但只有 * syntical * 引号才适用。当您添加文字引号时,软件将查找名称本身中包含"字符的文件名。

文档的更正版本可能如下所示:

{
  "exec": {
    "apiVersion": "client.authentication.k8s.io/v1beta1",
    "args": [
      "-c",
      "sops --decrypt \"${tokens_file}\" | jq -cM '{\"kind\": \"ExecCredential\", \"apiVersion\": \"client.authentication.k8s.io/v1beta1\", \"spec\": {}, \"status\" : {\"token\":.tokens[$ENV.context]}}'"
    ],
    "command": "bash",
    "env": [
      {
        "name": "context",
        "value": "utility"
      },
      {
        "name": "tokens_file",
        "value": "/home/some-user/.kube/tokens with space in name.enc.json"
      }
    ]
  }
}

相关问题