如何确定JQ中是否存在数组



嗨,所以我有一个curl命令来检查api上的一些数据,然后使用jq来解析数据,只查找相关信息。

问题是有些数据包含一个称为.result.CVE_Items[].configurations.nodes[].children[]的类,但其他数据没有。因此,我正在尝试编写一个if、elif和else语句来解析数据。我正试图弄清楚如何放置一个elif语句来检查这个类是否存在.result.CVE_Items[].configurations.nodes[].children[],以及它是否存在以查询数据。

下面是两个命令,其中一个包含类,另一个不包含类并带来错误:


# First command works: has the class 
curl -s https://services.nvd.nist.gov/rest/json/cve/1.0/CVE-2020-12389 | jq -r 'if .totalResults == 1 then . | {CVE: .result.CVE_Items[].cve.CVE_data_meta.ID, Description: .result.CVE_Items[].cve.description.description_data[].value, "CVSS V3 Score": .result.CVE_Items[].impact.baseMetricV3.cvssV3.baseSeverity, "Attack Vector": .result.CVE_Items[].impact.baseMetricV3.cvssV3.attackVector, "Privileges Required": .result.CVE_Items[].impact.baseMetricV3.cvssV3.privilegesRequired, "User Interaction": .result.CVE_Items[].impact.baseMetricV3.cvssV3.userInteraction, "Impact Score": .result.CVE_Items[].impact.baseMetricV3.impactScore, "Products Affected": [.result.CVE_Items[].configurations.nodes[].children[].cpe_match[].cpe23Uri]} else . | {Results: .message} end'
Output:
{
"CVE": "CVE-2020-12389",
"Description": "The Firefox content processes did not sufficiently lockdown access control which could result in a sandbox escape. *Note: this issue only affects Firefox on Windows operating systems.*. This vulnerability affects Firefox ESR < 68.8 and Firefox < 76.",
"CVSS V3 Score": "CRITICAL",
"Attack Vector": "NETWORK",
"Privileges Required": "NONE",
"User Interaction": "NONE",
"Impact Score": 6,
"Products Affected": [
"cpe:2.3:a:mozilla:firefox:*:*:*:*:*:*:*:*",
"cpe:2.3:a:mozilla:firefox_esr:*:*:*:*:*:*:*:*",
"cpe:2.3:o:microsoft:windows:-:*:*:*:*:*:*:*"
]
}

# Second command as the above but different data output and doesn't contain the class hence errors out.
curl -s https://services.nvd.nist.gov/rest/json/cve/1.0/CVE-2020-0796 | jq -r 'if .totalResults == 1 then . | {CVE: .result.CVE_Items[].cve.CVE_data_meta.ID, Description: .result.CVE_Items[].cve.description.description_data[].value, "CVSS V3 Score": .result.CVE_Items[].impact.baseMetricV3.cvssV3.baseSeverity, "Attack Vector": .result.CVE_Items[].impact.baseMetricV3.cvssV3.attackVector, "Privileges Required": .result.CVE_Items[].impact.baseMetricV3.cvssV3.privilegesRequired, "User Interaction": .result.CVE_Items[].impact.baseMetricV3.cvssV3.userInteraction, "Impact Score": .result.CVE_Items[].impact.baseMetricV3.impactScore, "Products Affected": [.result.CVE_Items[].configurations.nodes[].children[].cpe_match[].cpe23Uri]} else . | {Results: .message} end'
Output:
jq: error (at <stdin>:0): Cannot iterate over null (null)
# Error is mainly at the Products affected .... when you remove .children[] it works

curl -s https://services.nvd.nist.gov/rest/json/cve/1.0/CVE-2020-0796 | jq -r 'if .totalResults == 1 then . | {CVE: .result.CVE_Items[].cve.CVE_data_meta.ID, Description: .result.CVE_Items[].cve.description.description_data[].value, "CVSS V3 Score": .result.CVE_Items[].impact.baseMetricV3.cvssV3.baseSeverity, "Attack Vector": .result.CVE_Items[].impact.baseMetricV3.cvssV3.attackVector, "Privileges Required": .result.CVE_Items[].impact.baseMetricV3.cvssV3.privilegesRequired, "User Interaction": .result.CVE_Items[].impact.baseMetricV3.cvssV3.userInteraction, "Impact Score": .result.CVE_Items[].impact.baseMetricV3.impactScore, "Products Affected": [.result.CVE_Items[].configurations.nodes[].cpe_match[].cpe23Uri]} else . | {Results: .message} end'
Output:
{
"CVE": "CVE-2020-0796",
"Description": "A remote code execution vulnerability exists in the way that the Microsoft Server Message Block 3.1.1 (SMBv3) protocol handles certain requests, aka 'Windows SMBv3 Client/Server Remote Code Execution Vulnerability'.",
"CVSS V3 Score": "CRITICAL",
"Attack Vector": "NETWORK",
"Privileges Required": "NONE",
"User Interaction": "NONE",
"Impact Score": 6,
"Products Affected": [
"cpe:2.3:o:microsoft:windows_10:1903:*:*:*:*:*:*:*",
"cpe:2.3:o:microsoft:windows_10:1909:*:*:*:*:*:*:*",
"cpe:2.3:o:microsoft:windows_server_2016:1903:*:*:*:*:*:*:*",
"cpe:2.3:o:microsoft:windows_server_2016:1909:*:*:*:*:*:*:*"
]
}

我试过has("children"(和has("children[]"(,但都没用,我真的不知道,我已经检查了在解析之前检查元素时提出的所有github问题,还搜索了stackoverflow。我也检查了文件。我希望它在一个命令中,首先检查totalResults==1,并有(children(==false来查询信息elif totalResults==1,有(childrens(==true来查询信息,否则打印出错误消息,这意味着数据不可用。

请协助

谢谢。

\n00b

所以@peak给了我一些关于如何解决这个问题的想法。。。这个代码解决了这个问题。

curl -s https://services.nvd.nist.gov/rest/json/cve/1.0/CVE-2020-11066 
| jq -r 'if .totalResults == 1 then .result.CVE_Items[] 
| .cve.CVE_data_meta.ID as $ID 
| .cve.description.description_data[].value as $value 
| .configurations.nodes[] as $node 
| if $node | (type == "object" and has("children")) 
then .impact.baseMetricV3 | 
{CVE: $ID, Description: $value, 
"CVSS V3 Score": .cvssV3.baseSeverity, 
"Attack Vector": .cvssV3.attackVector, 
"Privileges Required": .cvssV3.privilegesRequired, 
"User Interaction": .cvssV3.userInteraction, 
"Impact Score": .impactScore, 
"Products Affected": [$node.children[].cpe_match[].cpe23Uri]} 
else .impact.baseMetricV3 | 
{CVE: $ID, Description: $value, 
"CVSS V3 Score": .cvssV3.baseSeverity, 
"Attack Vector": .cvssV3.attackVector, 
"Privileges Required": .cvssV3.privilegesRequired, 
"User Interaction": .cvssV3.userInteraction, 
"Impact Score": .impactScore, 
"Products Affected": [$node.cpe_match[].cpe23Uri]} 
end else . | {Results: .message} end'

所以基本上,如果你按照上面的答案,@peak向我们展示了如何放置if语句来检查对象类的子级是否存在于if语句中。其他声明解决了我们的问题,我们可以继续了。

一个巧妙的答案是说使用以下if/then/else结构:

if .result.CVE_Items[].configurations.nodes[] | has("children")
then ...
else ...
end

但是,如果每个数组的长度都等于1,那该怎么说呢?或者nodes数组中的项是JSON对象?

因此,也许最好写这样的东西:

.result.CVE_Items[0].configurations.nodes[0] as $node
| if ($node | ( type == "object" and has("children") ))
then ...
else ...
end

但查询的其余部分也存在同样的问题,这不仅会产生错误,还会产生不必要的组合爆炸。

因此,您可能应该在过程中引入jq变量,以确保您只选择您真正想要的项目,如下面的部分所示。

请注意:你可以简单地写E.而不是(.|E(

示例

if .totalResults == 1 
then .result.CVE_Items[] 
| .cve.CVE_data_meta.ID as $ID
| .cve.description.description_data[].value as $value
| .configurations.nodes[] as $node
| if $node | (type == "object" and has("children"))
then .impact.baseMetricV3
|  {CVE: $ID,
Description: $value, 
"CVSS V3 Score":  .cvssV3.baseSeverity,
"Attack Vector":  .cvssV3.attackVector,
"Privileges Required": .cvssV3.privilegesRequired,
"User Interaction": .cvssV3.userInteraction,
"Impact Score": .impactScore,
"Products Affected": [$node.children[].cpe_match[].cpe23Uri]}
else {Results: .message} 
end
else {Results: .message} 
end

最新更新