然而努力用jq解析JSON

时间:2017-06-08 07:05:45

标签: json csv jq

我正在慢慢掌握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"

相同的结果,只显示在一行中。 我走过手册页,摆弄了一会儿无济于事。 是可以这样做还是我需要一个不同的工具来操纵它?

提前致谢!

2 个答案:

答案 0 :(得分:4)

首先让我们讨论一下你收到这个结果的原因。

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

.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

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

答案 1 :(得分:3)

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

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

顺便说一句,没有必要使用cat

jq -r -f program.jq test.json