如何将“键:值”序列转换为JSON?

时间:2018-10-31 17:39:09

标签: bash key-value jq

好的,我正在尝试编写一个脚本,该脚本从yum - repolist all中获取信息,并将其放入漂亮的JSON中,以便我用于某些数据收集。.现在,我的yum命令输出如下这个。

我现在拥有的所有代码只是yum repolist命令。

#!/bin/bash -x yum -v repolist all | grep -B2 -A6 "enabled" | sed 's/[[:space:]]//g' , 's/--//g' , 's/name=name=/name=/g'

该命令的输出如下:

Repo-id: wazuh_repo
Repo-name: Wazuhrepository
Repo-status: enabled
Repo-revision: 1536348945
Repo-updated: FriSep712:35:512018
Repo-pkgs: 73
Repo-size: 920M
Repo-baseurl: https://packages.wazuh.com/3.x/yum/
Repo-expire: 21,600second(s)(last:WedOct3108:59:002018)

大约有8个条目,标题始终是相同的...有人可以像我五岁时那样解释如何将其转换为json,我已经阅读了jq手册页,也已经了解了散列。似乎没有任何意义。我知道我需要一个“键” /“值”,如何指定这些?

我只想获取输出并使它看起来像漂亮的JSON,这是我正在编写的一个较大脚本的一部分,以帮助保持我们在工作中使用的存储库的顶部。我只是完全没有得到JSON。

编辑:我宁愿不使用包装器功能并做/学习正确的方法

3 个答案:

答案 0 :(得分:2)

因此,首先,让没有yum的人可以测试一下,让我们做一个包装函数:

write_output() { cat <<EOF
Repo-id: wazuh_repo
Repo-name: Wazuhrepository
Repo-status: enabled
Repo-revision: 1536348945
Repo-updated: FriSep712:35:512018
Repo-pkgs: 73
Repo-size: 920M
Repo-baseurl: https://packages.wazuh.com/3.x/yum/
Repo-expire: 21,600second(s)(last:WedOct3108:59:002018)
EOF
}

值得注意的是,您所有的键都在字符串:之前,而值在它们之后-因此,我们想逐行读取,基于冒号-空格序列进行拆分,处理前面的内容作为键,然后将背后的内容视为值。


鉴于:

jq -Rn '[inputs | split(": ")] | reduce .[] as $kv ({}; .[$kv[0]] = $kv[1])' < <(write_output)

...正确发射:

{
  "Repo-id": "wazuh_repo",
  "Repo-name": "Wazuhrepository",
  "Repo-status": "enabled",
  "Repo-revision": "1536348945",
  "Repo-updated": "FriSep712:35:512018",
  "Repo-pkgs": "73",
  "Repo-size": "920M",
  "Repo-baseurl": "https://packages.wazuh.com/3.x/yum/",
  "Repo-expire": "21,600second(s)(last:WedOct3108:59:002018)"
}

...那么,它如何工作?

  • jq -R打开原始输入模式;输入被解析为原始字符串序列,而不是JSON文档序列。
  • jq -nnull视为唯一的直接输入,因此可以在需要时在脚本中使用inputinputs原语。
  • [ inputs ]读取所有输入行,并将它们放入单个数组中。
  • [ inputs | split(": ")]将其从字符串数组更改为列表数组-内容在": "序列之前和之后。
  • reduce .[] as $kv ( {}; ... )启动一个 reduceer ,其初始值为{},然后馈送.[]求值的每个值(也就是说,每个列表中的项目)作为...变量放入该化简器($kv代码)中,每次替换.值。

要使用yum命令作为实际输入运行此命令,请将< <(write_output)更改为< <(yum -v repolist all | grep -B2 -A6 "enabled" | sed 's/[[:space:]]//g' , 's/--//g' , 's/name=name=/name=/g')

答案 1 :(得分:0)

这里是@CharlesDuffy答案的更强大的变体。由于后者提供了很好的解释性注释,因此此处不再赘述。

jq -nR '
  [inputs | index(": ") as $ix | {(.[:$ix]): .[$ix+2:]}]
  | add'

在“值”包含“:”的情况下,这避免使用split。但是,最好不要假设空格位于第一个相关的“:”之后。

还请注意,此处使用add代替reduce只是为了紧凑和简单。

答案 2 :(得分:0)

对于这类问题,我宁愿使用正则表达式来匹配键和值。否则,我将采用与Charles相似的方法。

$ ... | jq -Rn 'reduce (inputs | capture("(?<k>[^:]+):\\s*(?<v>.+)")) as {$k, $v} ({}; .[$k] = $v)'