jq保留捕获组中缺少的数组对象并更新数组

时间:2018-04-12 15:10:46

标签: if-statement jq

  

输入

[{
        "tags": [{
                "value": "domain:sourcing"
            },
            {
                "value": "apiname:src1"
            }
        ]
    },
    {
        "tags": [{
            "value": "apiname:fin1"
        }]
    },
    {
        "tags": [{
            "value": "domain:fin1"
        }]
    }
]
  

预期输出

[{
        "domain": "sourcing",
        "apiname": "src1"
    },
    {
        "domain": "-",
        "apiname": "fin1"
    },
    {
        "domain": "fin1",
        "apiname": "-"
    }
]

到目前为止,我在下面尝试过。

jq 'map(. + (.tags[].value | capture("domain:(?<domain>.+)"))) | map(. + (.tags[].value | capture("apiname:(?<apiname>.+)"))) | map(del(.tags))'

  

以上cmd的部分输出

[
  {
    "apiDomain": "sourcing",
    "apiName": "src1"
  }
]

正如您所看到的,这里的问题是如果没有任何一个捕获组提交,我将完全失去其他对象。输入中的第二个对象具有 apiname 但缺少“domain”,第三个对象具有“domain”但缺少“apiname”。如示例输出中所述,如果没有任何对象,则它们应为“ - ”

请更新jq命令以实现此目的吗?

3 个答案:

答案 0 :(得分:1)

jq 解决方案:

jq '{domain: "-", apiname: "-"} as $o 
    | map([.tags[] | .value | split(":") | {(.[0]) : .[1]}] | add | $o + .)' input.json
  • {domain: "-", apiname: "-"} as $o - 用作模板对象

输出:

[
  {
    "domain": "sourcing",
    "apiname": "src1"
  },
  {
    "domain": "-",
    "apiname": "fin1"
  },
  {
    "domain": "fin1",
    "apiname": "-"
  }
]

答案 1 :(得分:1)

这是另一种方法。这假设您的tags数组仅包含您期望的名称。

map(
    reduce (.tags[].value | split(":")) as [$k,$v] (
        {domain:"-",apiname:"-"};
        .[$k] = $v
    )
)

对于没有假设固定名称并且只是展平标签的更通用的解决方案,我执行此操作:

map(
    reduce (.tags[].value | split(":")) as [$k,$v] (
        del(.tags);
        .[$k] = $v
    )
)

然后在访问字段时,只需使用替代运算符设置默认值。

(.domain // "-") as $domain

答案 2 :(得分:1)

如果“tag:value”字符串的“value”部分可能包含冒号(“:”),那么使用split会变得不必要地棘手(甚至可能效率低下),所以它可能更容易使用capture,或许沿着@RomanPerekhrest建议的行:

{domain:"-", apiname:"-"} as $default
| map([.tags[].value
       | capture("(?<k>[^:]*):(?<v>.*)")
       | {(.k): .v} ]
      | add
      | $default + .)