然而努力用 jq 解析 JSON
Yet struggling to parse JSON with 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"
相同的结果,只是显示在一行中。
我浏览了手册页并摆弄了一段时间无济于事。
是否可以这样做,或者我需要一个不同的工具来操纵它?
提前致谢!
要在 CSV 行中打印的所有值必须收集在 JSON 数组中。因此,与您的尝试非常相似的解决方案是:
.sites[]
| [.site_id, .domain, (.security.waf.rules[] | .action_text) ]
| @csv
对了,不用cat
:
jq -r -f program.jq test.json
首先让我们讨论一下您收到该结果的原因。
当您使用 []
从 objects/arrays 中提取项目时,它会为 object/array 中的每个项目生成一个值。
.sites[]
为 sites
数组中的每个值生成一个结果(在本例中只有一个)。
还有一点需要注意,使用逗号 (,
) 将在该表达式中产生分隔值。
[.site_id,.domain]
这里的逗号产生两个值,site_id
和domain
。但是,这些值被收集到一个数组中(如方括号所示)。
将其放入表达式的下一部分
.security.waf.rules[] | [.action_text]
第一部分遍历该数组中的所有规则对象。然后为每个对象创建一个包含 action_text
的数组。这将创建三个数组(每个规则一个)。
将其与表达式的前一部分放在一起(稍微重新格式化)
([.site_id,.domain]) , (.security.waf.rules[] | [.action_text])
这一切一起产生四个数组,包含 site_id
和 domain
的数组,然后是 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
当然,您可以采用多种方法来获取这些值(例如分别构建数组然后组合它们),但这是最直接的方法。
我正在慢慢掌握 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"
相同的结果,只是显示在一行中。 我浏览了手册页并摆弄了一段时间无济于事。 是否可以这样做,或者我需要一个不同的工具来操纵它?
提前致谢!
要在 CSV 行中打印的所有值必须收集在 JSON 数组中。因此,与您的尝试非常相似的解决方案是:
.sites[]
| [.site_id, .domain, (.security.waf.rules[] | .action_text) ]
| @csv
对了,不用cat
:
jq -r -f program.jq test.json
首先让我们讨论一下您收到该结果的原因。
当您使用 []
从 objects/arrays 中提取项目时,它会为 object/array 中的每个项目生成一个值。
.sites[]
为 sites
数组中的每个值生成一个结果(在本例中只有一个)。
还有一点需要注意,使用逗号 (,
) 将在该表达式中产生分隔值。
[.site_id,.domain]
这里的逗号产生两个值,site_id
和domain
。但是,这些值被收集到一个数组中(如方括号所示)。
将其放入表达式的下一部分
.security.waf.rules[] | [.action_text]
第一部分遍历该数组中的所有规则对象。然后为每个对象创建一个包含 action_text
的数组。这将创建三个数组(每个规则一个)。
将其与表达式的前一部分放在一起(稍微重新格式化)
([.site_id,.domain]) , (.security.waf.rules[] | [.action_text])
这一切一起产生四个数组,包含 site_id
和 domain
的数组,然后是 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
当然,您可以采用多种方法来获取这些值(例如分别构建数组然后组合它们),但这是最直接的方法。