【问题标题】:Yet struggling to parse JSON with jq然而,努力用 jq 解析 JSON
【发布时间】:2017-11-09 18:18:32
【问题描述】:

我正在慢慢掌握 jq 的工作原理,但距离掌握它还很遥远。 现在我处于一种我已经设法得到我想要的东西但没有以我想要的方式展示它的情况。我敢肯定这很简单,但我想念它......

这是我要解析的 JSON 示例:

{
    "sites": [
        {
            "site_id": 123456,
            "status": "configured",
            "domain": "www.domain.com",
            "account_id": 654321,
            "security": {
                "waf": {
                    "rules": [
                        {
                            "action": "block_request",
                            "action_text": "Block",
                            "id": "sqli",
                            "name": "SQLi"
                        },
                        {
                            "action": "block_request",
                            "action_text": "Block",
                            "id": "xss",
                            "name": "XSS"
                        },
                        {
                            "action": "alert",
                            "action_text": "Alert",
                            "id": "path_vector",
                            "name": "Path Vector"
                        }
                    ]
                }
            }
        }
    ],
    "res": 0,
    "res_message": "OK",
    "debug_info": {
        "id-info": "9123"
    }
}

我只需要一些细节并将它们以 CSV 格式保存,这是我目前所做的:

cat test.json | jq -r '.sites [] | [.site_id,.domain],(.security.waf.rules[] | [.action_text]) | @csv'

这是我得到的输出:

123456,"www.domain.com"
"Block"
"Block"
"Alert"

还不错,但我正在寻找的是这样的:

123456,"www.domain.com","Block","Block","Alert"

同样的结果,只是显示在一行中。 我浏览了手册页并摆弄了一段时间无济于事。 是否可以这样做,或者我需要一个不同的工具来操作它?

提前致谢!

【问题讨论】:

    标签: json csv export-to-csv jq


    【解决方案1】:

    首先让我们讨论一下您收到该结果的原因。

    当您使用[] 从对象/数组中提取项目时,它会为该对象/数组中的每个项目生成一个值。

    .sites[]
    

    sites 数组中的每个值生成一个结果(在这种情况下只有一个)。

    另外需要注意的是,使用逗号 (,) 将在该表达式中产生分隔值。

    [.site_id,.domain]
    

    这里的逗号产生两个值,site_iddomain。但是,这些值被收集到一个数组中(如方括号所示)。

    把它放到表达式的下一部分

    .security.waf.rules[] | [.action_text]
    

    第一部分遍历该数组中的所有规则对象。然后为每个对象创建一个包含action_text 的数组。这将创建三个数组(每个规则一个)。

    把它和表达式的前一部分放在一起(稍微重新格式化)

    ([.site_id,.domain]) , (.security.waf.rules[] | [.action_text])
    

    这一切一起产生了四个数组,数组包含site_iddomain,然后是三个数组action_text

    然后,对于这四个数组中的每一个,都会创建一个 csv 行,为您提供所看到的结果。


    那么我们怎样才能得到想要的结果呢?

    首先,我们要开始浏览所有网站。我假设您希望每个站点有一行。

    .sites[]
    

    然后,对于每个站点,我们需要为该行中的值构建一个数组。从我们可以直接访问的内容开始。

    .site_id, .domain
    

    然后产生action_text 值。

    .security.waf.rules[].action_text
    

    请注意,我们不会将 action_text 放在单独的数组中,我们只需要该值。

    现在我们将这些值放在一起。

    .site_id, .domain, (.security.waf.rules[].action_text)
    

    正如我们所讨论的,这会创建五个值,但我们希望将它们收集到一个数组中,以便将其传递给 @csv 过滤器。

    [.site_id, .domain, (.security.waf.rules[].action_text)]
    

    把所有东西放在一起就会得到这个过滤器:

    .sites[] | [.site_id, .domain, (.security.waf.rules[].action_text)] | @csv
    

    当然,您可以采用多种方法来获取这些值(例如分别构建数组然后组合它们),但这是最直接的。

    【讨论】:

    • 真棒@Jeff Mercado !!!也非常感谢您的详尽解释!
    【解决方案2】:

    要在 CSV 行中打印的所有值都必须收集在 JSON 数组中。因此,与您的尝试非常相似的解决方案是:

    .sites[]
    | [.site_id, .domain, (.security.waf.rules[] | .action_text) ]
    | @csv
    

    对了,不用cat

    jq -r -f program.jq test.json
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-16
      • 2011-04-25
      • 1970-01-01
      • 2020-11-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多