【问题标题】:jq: how to loop through sub arraysjq:如何遍历子数组
【发布时间】:2021-12-14 17:24:59
【问题描述】:

我有以下数据集:

{
  "data": {
    "activeFindings": {
      "findings": [
        {
          "findingId": "someFindingID#84209",
          "products": [
            "hostA.corp.somedomain.org",
            "hostB.corp.somedomain.org"
          ],
          "totalAffectedObjectsCount": 6
        },
        {
          "findingId": "someFindingID#2145016",
          "products": [
            "hostC.corp.somedomain.org"
          ],
          "totalAffectedObjectsCount": 1
        },
        {
          "findingId": "someFindingID#67129",
          "products": [
            "hostD.corp.somedomain.org"
          ],
          "totalAffectedObjectsCount": 4
        },
        {
          "findingId": "someFindingID#67774",
          "products": [
            "hostA.corp.somedomain.org"
          ],
          "totalAffectedObjectsCount": 6
        }
      ]
    }
  }
}

以下命令(尽管第一个结果返回 null)将给出 findingID 及其关联主机的列表:

cat test | jq -r '.data[] | .. | "\(.findingId?) \(.products?)"'
null null
someFindingID#84209 ["hostA.corp.somedomain.org","hostB.corp.somedomain.org"]
someFindingID#2145016 ["hostC.corp.somedomain.org","hostE.corp.somedomain.org","hostG.corp.somedomain.org"]
someFindingID#67129 ["hostD.corp.somedomain.org"]
someFindingID#67774 ["hostA.corp.somedomain.org"]

我想要实现的是遍历每个值并将 findingIdproducts 作为 bash 脚本中的参数传递。

以下内容:

someFindingID#84209 ["hostA.corp.somedomain.org","hostB.corp.somedomain.org"]
someFindingID#2145016 ["hostC.corp.somedomain.org","hostE.corp.somedomain.org","hostG.corp.somedomain.org"]
someFindingID#67129 ["hostD.corp.somedomain.org"]
someFindingID#67774 ["hostA.corp.somedomain.org"]

会导致:

./somescript.sh someFindingID#84209 hostA.corp.somedomain.org
./somescript.sh someFindingID#84209 hostB.corp.somedomain.org
./somescript.sh someFindingID#2145016 hostC.corp.somedomain.org
./somescript.sh someFindingID#2145016 hostE.corp.somedomain.org
./somescript.sh someFindingID#2145016 hostG.corp.somedomain.org
./somescript.sh someFindingID#67129 hostD.corp.somedomain.org
[...]

任何有关如何实现上述目标的帮助/指导将不胜感激!

谢谢,

【问题讨论】:

    标签: json jq


    【解决方案1】:

    解决方案:

    jq -r '
       .data[][][] |
       .products[] as $product |
       @sh "./somescript.sh \( .findingId ) \( $product )"
    '
    

    首先,.data[] | .. 返回的节点太多。

    • .data[][][] 在这里会很好用。
    • 如果您想更精确,可以使用.data.activeFindings.findings[]

    你问如何循环,但你已经在这样做了:[] 用于循环数组。

    问题是你想在不改变上下文的情况下循环(.)。为此,我们可以使用as:

    .products[] as $product
    

    最后,我们想避免code injection 错误,所以我们将使用@sh "..."。在@sh 后面的字符串文字中,所有的内插值都被转换为正确的shell 字符串文字。

    $ jq -rn '"foo bar" | @sh "cmd \( . )"'
    cmd 'foo bar'
    

    综上所述,我们得到以下程序:

    .data[][][] |
    .products[] as $product |
    @sh "./somescript.sh \( .findingId ) \( $product )"
    

    Demojqplay

    【讨论】:

    • 完美运行,感谢您的详细解答和帮助!
    【解决方案2】:

    我会选择这样的:

    jq -r '.data[]
    | .. 
    | objects
    | select(has("findingId"))
    | "./somescript.sh \"\(.findingId)\" " + .products[]
    '
    

    您可能还想引用“产品”值。 或者考虑使用@sh

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-30
      • 1970-01-01
      • 2011-10-30
      • 1970-01-01
      相关资源
      最近更新 更多