问题
I have a complex JSON file and I am trying to get the below result using JQ.
Expected Result:
{
"Host": "Test.example.com",
"Title": "Ensure message of the day is configured properly",
"Status": "passed"
}
{
"Host": "Test.example.com",
"Title": "Ensure bond0 is present",
"Status": "passed"
}
{
"Host": "Test.example.com",
"Title": "Ensure the SELinux state is disabled",
"Status": "passed"
}
Below is the JSON file that I get as a result of running an Chef Inspec profile.
JSON FILE:
{
"platform": {
"name": "redhat",
"release": "7.7",
"target_id": "Test.example.com"
},
"profiles": [
{
"name": "my-test",
"version": "0.1.0",
"sha256": "6fea36d6c12b21cd51274774edb4200d983db45c4cfa8172eebb897b6f3db8fe",
"title": "InSpec Profile",
"maintainer": "The Authors",
"summary": "An InSpec Compliance Profile",
"license": "Apache-2.0",
"copyright": "The Authors",
"copyright_email": "you@example.com",
"supports": [
{
"platform": "os"
}
],
"attributes": [],
"groups": [
{
"id": "controls/1_motd.rb",
"controls": [
"1.1 motd check"
],
"title": "Warning Banners"
},
{
"id": "controls/6_network.rb",
"controls": [
"6.1 Bonding"
]
},
{
"id": "controls/12_selinux.rb",
"controls": [
"Selinux Config"
]
}
],
"controls": [
{
"id": "1.1 motd check",
"title": "Ensure message of the day is configured properly",
"desc": "Ensure message of the day is configured properly",
"descriptions": [
{
"label": "default",
"data": "Ensure message of the day is configured properly"
}
],
"impact": 1,
"refs": [],
"tags": {},
"code": "control '1.1 motd check' do\n title 'Ensure message of the day is configured properly'\n desc \"The contents of the /etc/motd file are displayed to users after login and function as a message of the day for authenticated users.\"\n desc \"Ensure message of the day is configured properly\"\n impact 1.0\n \n describe file('/etc/motd') do\n its('content') { should_not be_empty }\n end\nend\n",
"source_location": {
"line": 3,
"ref": "my-test/controls/1_motd.rb"
},
"waiver_data": {},
"results": [
{
"status": "passed",
"code_desc": "File /etc/motd content should not be empty",
"run_time": 0.099938054,
"start_time": "2020-02-07T11:31:47+11:00"
}
]
},
{
"id": "6.1 Bonding",
"title": "Ensure bond0 is present",
"desc": "Check bonding is present",
"descriptions": [
{
"label": "default",
"data": "Check bonding is present"
}
],
"impact": 1,
"refs": [],
"tags": {},
"code": "control '6.1 Bonding' do\n title 'Ensure bond0 is present'\n desc \"Check bonding is present\"\n impact 1.0\n \n only_if { sys_info.manufacturer != \"VMware, Inc.\" } \n\n describe bond('bond0') do\n it { should exist }\n its('mode') { should eq 'IEEE 802.3ad Dynamic link aggregation' }\n end\nend\n",
"source_location": {
"line": 1,
"ref": "my-test/controls/6_network.rb"
},
"waiver_data": {},
"results": [
{
"status": "skipped",
"code_desc": "No-op",
"run_time": 9.02e-06,
"start_time": "2020-02-07T11:31:47+11:00",
"resource": "No-op",
"skip_message": "Skipped control due to only_if condition."
}
]
},
{
"id": "Selinux Config",
"title": "Ensure the SELinux state is disabled",
"desc": "Set SELinux to diabled",
"descriptions": [
{
"label": "default",
"data": "Set SELinux to diabled"
}
],
"impact": 1,
"refs": [],
"tags": {},
"code": "control 'Selinux Config' do\n title 'Ensure the SELinux state is disabled'\n desc \"Set SELinux to diabled\"\n impact 1.0\n\n describe file('/etc/selinux/config') do\n its(:content) { should match(/^SELINUX=disabled\\s*(?:#.*)?$/) }\n end\nend\n",
"source_location": {
"line": 1,
"ref": "my-test/controls/12_selinux.rb"
},
"waiver_data": {},
"results": [
{
"status": "passed",
"code_desc": "File /etc/selinux/config content should match /^SELINUX=disabled\\s*(?:#.*)?$/",
"run_time": 0.120881444,
"start_time": "2020-02-07T11:31:47+11:00"
}
]
}
],
"status": "loaded"
}
],
"statistics": {
"duration": 0.223533139
},
"version": "4.18.24"
}
I used the following JQ code to extract the fields , but the extracted values are repeating.
JQ Code:
jq '{Host: .platform.target_id,Title: .profiles[].controls[].title,Status: .profiles[].controls[].results[].status}'
The result which I got from above JQ filter
Actual Result:
{
"Host": "Test.example.com",
"Title": "Ensure message of the day is configured properly",
"Status": "passed"
}
{
"Host": "Test.example.com",
"Title": "Ensure message of the day is configured properly",
"Status": "skipped"
}
{
"Host": "Test.example.com",
"Title": "Ensure message of the day is configured properly",
"Status": "passed"
}
{
"Host": "Test.example.com",
"Title": "Ensure bond0 is present",
"Status": "passed"
}
{
"Host": "Test.example.com",
"Title": "Ensure bond0 is present",
"Status": "skipped"
}
{
"Host": "Test.example.com",
"Title": "Ensure bond0 is present",
"Status": "passed"
}
{
"Host": "Test.example.com",
"Title": "Ensure the SELinux state is disabled",
"Status": "passed"
}
{
"Host": "Test.example.com",
"Title": "Ensure the SELinux state is disabled",
"Status": "skipped"
}
{
"Host": "Test.example.com",
"Title": "Ensure the SELinux state is disabled",
"Status": "passed"
}
How can I get the expected results. Any help would be appreciated.
回答1:
Because you're iterating over profiles[]
more than once, you're combining the results of one such iteration with the results of another. To avoid that, iterate only once, and get both title
and results
from the same controls
list entry.
jq '
.platform.target_id as $target |
.profiles[].controls[] |
{ Host: $target,
Title: .title,
Status: .results[].status }
'
See this running against your input data at https://jqplay.org/s/_6KVDfIn3m
来源:https://stackoverflow.com/questions/60105691/jq-query-returning-too-many-records-unwanted-permutations