【问题标题】:unexpected loop cycles with jqjq 的意外循环循环
【发布时间】:2019-05-09 18:49:29
【问题描述】:

我正在尝试使用 jq 将 bash 中的表格从 json 打印到标准输出:

[
    {
      "key": "name",
      "doc_count": 1000,
      "values_over_time": {
        "buckets": [
          {
            "key_as_string": "2019-05-01 11:00:00.000",
            "key": 1556708400000,
            "doc_count": 50
          },
          {
            "key_as_string": "2019-05-02 12:00:00.000",
            "key": 1556798400000,
            "doc_count": 40
          },
          {
            "key_as_string": "2019-05-02 13:00:00.000",
            "key": 1556802000000,
            "doc_count": 30
          }
        ]
      }
    }
]

使用jq -r '(.[].key + " " + .[].values_over_time[][].key_as_string) + " " + (.[].values_over_time[][].doc_count|tostring)' 我得到以下结果:

"name 2019-05-01 11:00:00.000 50"
"name 2019-05-02 12:00:00.000 50"
"name 2019-05-02 13:00:00.000 50"
"name 2019-05-01 11:00:00.000 40"
"name 2019-05-02 12:00:00.000 40"
"name 2019-05-02 13:00:00.000 40"
"name 2019-05-01 11:00:00.000 30"
"name 2019-05-02 12:00:00.000 30"
"name 2019-05-02 13:00:00.000 30"

额外的循环级别有些奇怪,因为我希望只看到 3 行:

"name 2019-05-01 11:00:00.000 50"
"name 2019-05-02 12:00:00.000 40"
"name 2019-05-02 13:00:00.000 30"

阅读jq 文档,但无法理解以一种简洁的方式正确迭代的正确方法。你有什么线索吗?

JQplay code sample

【问题讨论】:

    标签: json jq


    【解决方案1】:

    您将 values_over_time 扩展了两次,因此生成了 3 * 3 = 9 个输出。改为这样做:

    .[] | .key + " " + (.values_over_time.buckets[] | "\(.key_as_string) \(.doc_count)")
    

    比较这两个命令可以清楚地看到区别:

    $ jq -nc '[1,2,3] | [.[]*.[]]'
    [1,2,3,2,4,6,3,6,9]
    
    $ jq -nc '[1,2,3] | [.[]|.*.]'
    [1,4,9]
    

    【讨论】:

    • 非常感谢 - 你是我大脑的救星!将尝试更多地尝试jq 语法和迭代,感谢这些示例。现在我也知道-nc 是一个随时可用的小游乐场。
    【解决方案2】:

    技术原因是您正在组合生成多个结果的表达式。而 jq 的操作方式,它将为这些子表达式的每个组合生成结果。

    查看您的过滤器和输入,以下是每个子表达式生成的结果数:

    (.[].key + " " + .[].values_over_time[][].key_as_string) + " " + (.[].values_over_time[][].doc_count|tostring)
    (1         1     3)                                        1     (3                                 | 1)
    (1 * 1 * 3 = 3)                                            1     (3 * 1 = 3)
     3 * 1 * 3 = 9
    

    这就是为什么您必须始终小心使用生成多个结果的表达式(例如,[])。

    正如 Oguz 指出的那样,您需要编写它以使输入在表达式中仅扩展一次。通常在过滤器的开头是最好的。

    这可以通过多种方式完成,我会这样写:

    .[] | "\(.key) \(.values_over_time.buckets[] | "\(.key_as_string) \(.doc_count)")"
    1   |   (1)     (3                           |   (1)               (1))
    1   |   (1)     (3                           | 1 * 1 = 1)
    1   |   (1)     (3 * 1 = 3)
    1   | (1 * 3 = 3)
    1 * 3 = 3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-02
      • 2018-09-07
      • 2018-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多