Объединить несколько вызовов JQ в один - PullRequest
3 голосов
/ 15 марта 2019

Я анализирую файл JSON следующим образом и присваиваю его переменным оболочки, которые я позже проверю, не является ли он пустым, и выполняю соответствующие действия над ним.

Я делаю это, используя следующие команды jq:

 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`

Мой 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"
}

Я не хочу использовать инструменты оболочки, такие как awk, для доступа к полям. Есть ли способ упростить это, используя jq и bash, чтобы не иметь 30 независимых вызовов jq для этого?

Ответы [ 2 ]

2 голосов
/ 15 марта 2019

У вас явно не так много вызовов jq.Просто сделайте это один раз, чтобы сбросить все пары ключ / значение и прочитать их в отдельных переменных оболочки

#!/usr/bin/env bash

while IFS= read -r line; do
    declare "$line"
done< <(jq -r 'to_entries[] | [.key,.value] | join("=")' json)

Теперь вы можете распечатать переменную из командной строки, имя которой совпадает с именем из ключа JSON,Чтобы обработать еще более надежные строки JSON, которые могут содержать буквенные символы новой строки, передайте вывод JSON с нулевым разделителем ("\u0000") и read обратно.

1 голос
/ 15 марта 2019

Предполагая, что указанные имена переменных bash действительны, наиболее надежный метод будет выглядеть следующим образом:

while IFS= read -d $'\0' -r line; do
    declare "$line"
done< <(data | jq -j -r 'to_entries[] | [.key, (.value | @sh)] | join("=") + "\u0000"' )

Обратите внимание на использование фильтра jq @sh.

...