将JSON对象传递给jq参数

时间:2017-11-14 02:04:28

标签: json bash parameter-passing jq data-processing

数据样本 - sample.json (完整示例:https://pastebin.com/KFkVmc2M

    {
      "ip": 3301234701,
      "_shodan": {
        "options": {
          "referrer": "7ae15507-f5cc-4353-b72e-5cc0b1c34c5e"
        },
      },
      "hash": -1056085507,
      "os": null,
      "title": "WHM Login",
      "opts": {
        "vulns": ["!CVE-2014-0160"],
        "heartbleed": "2017/08/29 09:57:30 196.196.216.13:2087 - SAFE\
        }
      },
      "isp": "Fiber Grid Inc",
      "http": {
        "redirects": [],
        "title": "WHM Login",
        "robots": null,
        "favicon": null,
        "host": "196.196.216.13",
        "html":
}

使用jq的脚本,我希望它可以工作,但尚未找到另一种解决方案。

   cat sample.json | jq \
   --arg key0   'Host' \
   --arg value0 '.host' \
   --arg key1   'Vulnerability' \
   --arg value1 '.opts.vulns[0]' \
   --arg key2   'ISP' \
   --arg value2 '.isp' \
   '. | .[$key0]= $value0 | .[$key1]=$value1 | .[$key2]=$value2' \
   <<<'{}'

我希望的最终结果,但没有得到:

{
  "Host": "196.196.216.13",
  "Vulnerability": "!CVE-2014-0160",
  "ISP": "Fiber Grid Inc"
}

现在它只是将对象作为字符串返回,我尝试了很多不同的方法来解决问题。我对使用JSON和jq很陌生,但根据我到目前为止所读到的内容,解决方案可能不像我希望的那样简单吗?

简单地说,为什么不将对象作为sample.json对象的值返回,我该怎么做才能使它工作?

谢谢!

to:chepner

{
  "196.196.216.13":[
  "AS63119",
  "Fiber Grid Inc",
  "2017-08-29T06:57:22.546423",
  "!CVE-2014-0160"
],
"196.196.216.14":[
  "AS63119",
  "Fiber Grid Inc",
  "2017-08-29T06:57:22.546423",
  "!CVE-2014-0160"
]
}

3 个答案:

答案 0 :(得分:2)

  1. jq不支持对jq表达式的评估 你尝试工作所需的方式。你可以做一些 shell插值,但最好使用JSON路径, 例如而不是--arg value0 .host,您可以写--arg value0 "host"等。在下文中,我使用了getpath/1

  2. 不需要在&#39;前面添加jq过滤器。 |&#39;

  3. 无论如何,假设pastebin的JSON内容在pastebin.json中,你可以写:

      jq \
       --arg key0        Host \
       --argjson value0  '["http","host"]' \
       --arg key1        Vulnerability \
       --argjson value1  '["opts", "vulns", 0]' \
       --arg key2        ISP \
       --argjson value2  '["isp"]' \
       '. as $in
        | {}
        | .[$key0] = ($in|getpath($value0))
        | .[$key1] = ($in|getpath($value1))
        | .[$key2] = ($in|getpath($value2))' \
       pastebin.json
    

    这将产生结果:

    {
      "Host": "196.196.216.13",
      "Vulnerability": "!CVE-2014-0160",
      "ISP": "Fiber Grid Inc"
    }
    

答案 1 :(得分:1)

这是使用@CharlesDuffy建议的方法的变体解决方案:

$ config='{"Host": ["http", "host"], 
           "Vulnerability": ["opts", "vulns", 0], 
           "ISP": ["isp"]}'
$ jq --argjson config "$config" '
   . as $in
   | $config
   | map_values( . as $p | $in | getpath($p) )' pastebin.json

输出:

{
  "Host": "196.196.216.13",
  "Vulnerability": "!CVE-2014-0160",
  "ISP": "Fiber Grid Inc"
}

顺便提一下@chepner的观点:$ config所需的保养和维护不亚于相应jq查询所需的维护和维护,而jq查询语言 - 按设计 - 提供了更大的灵活性。 / p>

答案 2 :(得分:1)

回应补充质询(“to:chepner”):

pastebin数据不包含“196.196.216.14”,因此补充问题不清楚,但您可能希望从以下开始:

jq '{(.ip_str): [.asn, .isp, .timestamp, opts.vulns[0] ]}' pastebin.json

这会产生:

{
  "196.196.216.13": [
    "AS63119",
    "Fiber Grid Inc",
    "2017-08-29T06:57:22.546423",
    "!CVE-2014-0160"
  ]
}

这里的关键点是.ip_str周围的一对括号。

正如其他地方所提到的,jq查询再次如此简单和直接,以至于参数化版本将提供任何优势似乎令人怀疑。