【问题标题】:How to target and count value with JQ?如何用 JQ 定位和计算价值?
【发布时间】:2020-12-14 11:28:51
【问题描述】:

来自这个文件:

[
    {
        "network": "X.X.X.1",
        "defaultGateway": "X.X.X.X",
        "ipAddressTab": [
            {
                "foo1": "10.0.0.1",
                "foo2": "network",
                "status": "reserved",
                "foo4": null,
                "foo5": null,
                "foo6": null,
                "foo7": null,
                "foo8": null,
                "foo9": null,
                "foo10": null,
                "foo11": null
            },
            {
                "foo1": "10.0.0.2",
                "foo2": "network",
                "status": "reserved",
                "foo4": null,
                "foo5": null,
                "foo6": null,
                "foo7": null,
                "foo8": null,
                "foo9": null,
                "foo10": null,
                "foo11": null
            },
            {
                "foo1": "10.0.0.3",
                "foo2": "network",
                "status": "reserved",
                "foo4": null,
                "foo5": null,
                "foo6": null,
                "foo7": null,
                "foo8": null,
                "foo9": null,
                "foo10": null,
                "foo11": null
             },
             {
                "foo1": "10.0.0.4",
                "status": "available"
             },
             {   
                "foo1": "10.0.0.5",
                "status": "available"
             },
             {
                "foo1": "10.0.0.6",
                "status": "available"
             },
             {
                "foo1": "10.0.0.7",
                "status": "available"
             }
        ],
        "full": false,
        "id": "xxx"
    },
     {
        "network": "X.X.X.2",
        "defaultGateway": "X.X.X.X",
        "ipAddressTab": [
            {
                "foo1": "10.0.0.1",
                "foo2": "network",
                "status": "reserved",
                "foo4": null,
                "foo5": null,
                "foo6": null,
                "foo7": null,
                "foo8": null,
                "foo9": null,
                "foo10": null,
                "foo11": null
            },
            {
                "foo1": "10.0.0.2",
                "foo2": "network",
                "status": "reserved",
                "foo4": null,
                "foo5": null,
                "foo6": null,
                "foo7": null,
                "foo8": null,
                "foo9": null,
                "foo10": null,
                "foo11": null
            },
            {
                "foo1": "10.0.0.3",
                "foo2": "network",
                "status": "reserved",
                "foo4": null,
                "foo5": null,
                "foo6": null,
                "foo7": null,
                "foo8": null,
                "foo9": null,
                "foo10": null,
                "foo11": null
             },
             {
                "foo1": "10.0.0.4",
                "status": "available"
             },
             {   
                "foo1": "10.0.0.5",
                "status": "available"
             },
             {
                "foo1": "10.0.0.6",
                "status": "available"
             },
             {
                "foo1": "10.0.0.7",
                "status": "available"
             }
        ],
        "full": false,
        "id": "xxx"
    }
]

# Just an example, there is more lines in my file

我可以保留我想要的信息:

cat myfile | jq 'map({network, full})'
[
  {
    "network": "X.X.X.1",
    "full": false
  },
  {
    "network": "X.X.X.2",
    "full": false
  }
]

现在我正在寻找一个技巧来计算和显示一些值。例如,我想像这样显示保留、分配和可用的数量:

[
  {
    "network": "X.X.X.1",
    "full": false
    reserved: 3
    available: 4

    

  },
  {
    "network": "X.X.X.2",
    "full": false
    reserved: 3
    available: 4

  }
]

我到处寻找,但没有找到很好的例子......

有人告诉我如何获得这个输出?

谢谢!

【问题讨论】:

    标签: arrays json linux jq


    【解决方案1】:

    使用reduce 统计状态。

    map({network, full} +
      reduce .ipAddressTab[].status as $s ({}; .[$s] += 1))
    

    Online demo

    您可以将{} 更改为{reserved: 0, available: 0} 以保持所有条目中键的顺序一致。

    【讨论】:

      【解决方案2】:

      一种方法是使用函数来计算每种类型的对象

      def f($path; $val): $path | map(select(.status == $val)) | length;
      map({network, full, reserved: f(.ipAddressTab; "reserved"), available: f(.ipAddressTab; "available")})
      

      jqplay - Demo

      函数f 获取路径和要查找的状态字符串,然后获取数组中对象的长度。


      oguz ismail's建议避免重复

      def f($val): map(select(.status == $val)) | length; 
      map({network, full} + (.ipAddressTab | { reserved: f("reserved"), available: f("available")}))
      

      【讨论】:

        【解决方案3】:

        当计算潜在的大量对象时,通常最好 使用面向流的过滤器以避免构造数组。这两个通常作为一对有用,但在目前的情况下,仅定义 count/1 本身就足够了:

        def sigma(s): reduce s as $x (0; .+$x);
        
        def count(s): sigma(s|1);
        

        为了实现既定目标,现在可以简单地将规范编写为程序:

        
        map({network,
            full,
            reserved:   count(.ipAddressTab[] | select(.status == "reserved")),
            available:  count(.ipAddressTab[] | select(.status == "available"))
            })
        

        泛化

        现在来点 jq 魔法——根本不引用特定的“状态”值:

        def countStatus($s):
          {($s): count(.ipAddressTab[] | select(.status == $s))};
        
        def statuses: [.ipAddressTab[].status] | unique;
        
        map( {network, full}
             + ([countStatus(statuses[])] | add) )
        

        total_available

        在评论中,有人询问了有关显示total_available 的问题。 要为每个对象添加 total_available 键,您可以附加 遵循上述任一管道:

        | {total_available: sigma(.[] | .available)} as $total
        | map(. + $total)
        

        【讨论】:

        • 感谢您的解释!最后一件事,如果我想在 .available 之前添加所有值,我可以做类似{"total_available": sum(.available)} 的事情吗?
        • 对不起,问题不太清楚。您是否期待替代输出,或者是否应该将“total_available”键值对添加到现有输出数组中的每个对象?
        • 这个想法是添加一个变量“total_available”与每个“可用”的总和。所以在这种情况下,total_available 将等于 8。
        • 是的,但它去哪儿了?请参阅我之前的 Q。
        • 是的,另一种输出。我想在输出末尾有一个“total_available”字段,其中包含每个“可用”的总和。在我的情况下,total_available : 8. 这里(jqplay.org/s/cE3G5VqhT_)在每个 { ... } (
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多