首页 > 解决方案 > jq代码重写URL,其中一些值是数组和一些字符串

问题描述

在下面的 json 中,我需要重写configURL值并在staging.之后(并且仅)添加https://- 并忽略“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 而只有一个 URL 时才有效;我不知道如何为数组中的每个值添加条件和修改。

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

标签: jsonbashjq

解决方案


另一种方法是使用(.[]? // .)- 它本质上是一个 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.")'

推荐阅读