【问题标题】:jq code to rewrite URLs where some values are arrays and some stringsjq代码重写URL,其中一些值是数组和一些字符串
【发布时间】:2021-03-20 14:56:13
【问题描述】:

在以下 json 中,我需要重写 configURL 值并在(且仅)https:// 之后添加 staging. - 并忽略“http://”。问题是configURL 键存储的一些值是数组。原始 json 看起来像:

{
    "app1.json": {
        "content": "app-config",
        "updates": 2,
        "configURL": "https://companyX.com/app1/config.json"
    },
    "app2.json": {
        "content": "app-config",
        "updates": 2,
        "configURL": [
            "https://some-company.com/app2/config.json",
            "https://some-company.com/app2/config-resources.json",
            "http://some-company.com/app2/config-resources.json"
        ]
    },
    "app3.ini": {
        "content": "binaries",
        "scope": "deploy",
        "configURL": "https://staging.app4.com/app4/installs/binaries.ini",
        "resources": [
            "https://app4.com/resource",
            "https://app4.com/resource.bin",
            "https://app4.com/resource2.bin"
        ]
    },
    "app4.json": {
        "content": "app-config",
        "updates": 3,
        "configURL": [
            "https://different-company.com/app3/config.json",
            "https://different-company.com/app3/config-resources.json",
            "https://different-company.com/app3/config-binaries.json"
        ],
        "resources": [
            "https://different-company.com/resource",
            "https://different-company.com/resource.bin",
            "https://different-company.com/resource2.bin"
        ]
    }
}

想要的输出是


{
    "app1.json": {
        "content": "app-config",
        "updates": 2,
        "configURL": "https://staging.companyX.com/app1/config.json"
    },
    "app2.json": {
        "content": "app-config",
        "updates": 2,
        "configURL": [
            "https://staging.some-company.com/app2/config.json",
            "https://staging.some-company.com/app2/config-resources.json",
        ]
    },
    "app3.ini": {
        "content": "binaries",
        "scope": "deploy",
        "configURL": "https://staging.staging.app4.com/app4/installs/binaries.ini",
        "resources": [
            "https://app4.com/resource",
            "https://app4.com/resource.bin",
            "https://app4.com/resource2.bin"
        ]
    },
    "app4.json": {
        "content": "app-config",
        "updates": 3,
        "configURL": [
            "https://staging.different-company.com/app3/config.json",
            "https://staging.different-company.com/app3/config-resources.json",
            "https://staging.different-company.com/app3/config-binaries.json"
        ],
        "resources": [
            "https://different-company.com/resource",
            "https://different-company.com/resource.bin",
            "https://different-company.com/resource2.bin"
        ]
    }
}

我设法提出的以下解决方案仅在没有多个 URL 而只有一个时才有效;我不知道如何为数组中的每个值添加条件和修改。

jq -r 'def camel:gsub( "https://"; "https://staging."); walk( if type=="object" and .configURL then (.configURL |= camel) else . end)' apps.json

【问题讨论】:

  • 您可以询问某事物是什么类型,然后根据其结果进行分支(无论是数组还是单个值)。问题中给出的尝试是一个非常良好的开端。
  • ...实际上,您已经知道可以这样做,因为您在现有代码中使用了type
  • 也就是说,为什么你的示例数据有configURL,而你的示例代码有contentURL
  • 请明确指定如何处理 {"configURL": "http://"} - 在这种情况下是否应该完全删除密钥?另外:为什么gsub 而不是sub? “^https://”会更合适吗?

标签: json bash jq


【解决方案1】:

你已经检查了一个对象的type 一次——再做一次:

jq -r '
  def camel:
    if type == "string" then
      gsub( "https://"; "https://staging.")
    else
      .[] |= camel
    end;

  walk( if type=="object" and .configURL then (.configURL |= camel) else . end)
' apps.json

【讨论】:

    【解决方案2】:

    另一种方法是使用 (.[]? // .) - 它本质上是一个 if/else - ? 捕获错误,// . 返回原始值。

    $ jq -r '(.[].configURL | (.[]? // .))' apps.json
    https://companyX.com/app1/config.json
    https://some-company.com/app2/config.json
    https://some-company.com/app2/config-resources.json
    http://some-company.com/app2/config-resources.json
    https://staging.app4.com/app4/installs/binaries.ini
    https://different-company.com/app3/config.json
    https://different-company.com/app3/config-resources.json
    https://different-company.com/app3/config-binaries.json
    

    然后您可以直接转换结果。

    jq -r '(.[].configURL | (.[]? // .)) |= sub("^https://"; "https://staging.")'
    

    您的 configURL 键都在同一个位置,因此您不需要递归/遍历,但如果需要,您需要使用 select() 过滤掉潜在的空值

    jq -r '(.. | .configURL? | select(.) | (.[]? // .)) |= sub("^https://"; "https://staging.")'
    

    【讨论】:

      猜你喜欢
      • 2019-08-03
      • 2015-05-31
      • 2015-10-30
      • 2017-10-30
      • 1970-01-01
      • 2021-07-11
      • 1970-01-01
      • 2018-10-21
      • 2021-01-10
      相关资源
      最近更新 更多