Reputation: 165
I am parsing a JSON file as follows and assigning it to the shell variables that I later test if it is not empty and taking according actions on top of it.
I am doing this using following jq commands:
proxy_host=`jq -r .proxy_host <<< $line`
proxy_port=`jq -r .proxy_port <<< $line`
query_string=`jq -r .query_string <<< $line`
realip_remote_addr=`jq -r .realip_remote_addr <<< $line`
realpath_root=`jq -r .realpath_root <<< $line`
request_body=`jq -r .request_body <<< $line`
request_id=`jq -r .request_id <<< $line`
request_method=`jq -r .request_method <<< $line`
request_uri=`jq -r .request_uri <<< $line`
scheme=`jq -r .scheme <<< $line`
ssl_protocol=`jq -r .ssl_protocol <<< $line`
ssl_ciphers=`jq -r .ssl_ciphers <<< $line`
ssl_client_cert=`jq -r .ssl_client_cert <<< $line`
ssl_client_fingerprint=`jq -r .ssl_client_fingerprint <<< $line`
ssl_client_i_dn=`jq -r .ssl_client_i_dn <<< $line`
ssl_client_raw_cert=`jq -r .ssl_client_raw_cert <<< $line`
ssl_client_s_dn=`jq -r .ssl_client_s_dn <<< $line`
ssl_client_serial=`jq -r .ssl_client_serial <<< $line`
ssl_client_v_end=`jq -r .ssl_client_v_end <<< $line`
ssl_client_v_remain=`jq -r .ssl_client_v_remain <<< $line`
ssl_client_v_start=`jq -r .ssl_client_v_start <<< $line`
ssl_client_verify=`jq -r .ssl_client_verify <<< $line`
ssl_session_id=`jq -r .ssl_session_id <<< $line`
tcpinfo_rtt=`jq -r .tcpinfo_rtt <<< $line`
uri=`jq -r .uri <<< $line`
My json:
{
"host": "www.example.com",
"hostname": "localhost",
"proxy_add_x_forwarded_for": "127.0.0.1",
"proxy_host": "",
"proxy_port": "",
"query_string": "",
"realip_remote_addr": "8.1.2.3",
"realpath_root": "/var/www/",
"request_body": "",
"request_id": "78e7cc17c207fc683992bae956150c4d",
"request_method": "GET",
"request_uri": "/",
"scheme": "https",
"server_name": "www.localhost.com",
"ssl_protocol": "TLSv1.2",
"ssl_ciphers": "AES128-GCM-SHA256:AES128-SHA:AES256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:0x000a:0x00ff",
"ssl_client_cert": "",
"ssl_client_fingerprint": "",
"ssl_client_i_dn": "",
"ssl_client_raw_cert": "",
"ssl_client_s_dn": "",
"ssl_client_serial": "",
"ssl_client_v_end": "",
"ssl_client_v_remain": "",
"ssl_client_v_start": "",
"ssl_client_verify": "NONE",
"ssl_session_id": "3e10c1253816aa4b3ea80df403e752fadaa1c6e532febd25e288acb4f5735617",
"tcpinfo_rtt": "11142",
"uri": "/index.html"
}
I do not want to use shell tools like awk to access the fields. Is there a way to simplify this using jq and bash not to have 30 independent jq invocations to get this done?
Upvotes: 3
Views: 317
Reputation: 116740
Assuming the specified bash variable names are valid, the most robust method would be along these lines:
while IFS= read -d $'\0' -r line; do
declare "$line"
done< <(data | jq -j -r 'to_entries[] | [.key, (.value | @sh)] | join("=") + "\u0000"' )
Notice the use of the jq filter @sh
.
Upvotes: 1
Reputation: 85590
You obviously don't have do that many invocations of jq
. Just do it once to dump all the key/value pairs and read them out in separate shell variables
#!/usr/bin/env bash
while IFS= read -r line; do
declare "$line"
done< <(jq -r 'to_entries[] | [.key,.value] | join("=")' json)
Now you can print the variable from the command line having the same name as the one from the JSON key. To handle even more robust JSON strings that can contain literal newlines, emit the JSON output with a null-delimiter ("\u0000"
) and read
it back.
Upvotes: 2