如何将 "key: value" 序列转换为 JSON?
How can I convert a "key: value" sequence into JSON?
hokay,我正在尝试编写一个脚本,从 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 手册页,我已经阅读哈希的。似乎没有任何意义。我知道我需要有一个 "key"/"value" 如何指定这些?
我只想获取输出并使它看起来漂亮 JSON,这是我正在编写的更大脚本的一部分,以帮助掌握我们在工作中使用的存储库。不过,我完全没有得到 JSON。
编辑:我宁愿不使用包装函数和do/learn正确的方法
所以,首先,没有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
}
值得注意的是,您所有的键都在字符串 :
之前,而值在它们之后——所以我们要逐行读取,根据冒号-space 序列拆分,把前面的当作键,把后面的当作值。
鉴于:
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 -n
将 null
视为唯一的直接输入,因此可以在脚本中需要的地方使用 input
和 inputs
原语。
[ inputs ]
读取所有输入行,并将它们放入一个数组中。
[ inputs | split(": ")]
将其从字符串数组更改为列表数组——在 ": "
序列之前和之后都有内容。
reduce .[] as $kv ( {}; ... )
启动一个 reducer,初始值为 {}
,然后提供 .[]
求得的每个值(也就是说,您列表中的每个项目)作为 $kv
变量进入该减速器(...
代码),每次替换 .
值。
为了 运行 这个用你的 yum 命令作为真正的输入,改变 < <(write_output)
到 < <(yum -v repolist all | grep -B2 -A6 "enabled" | sed 's/[[:space:]]//g' , 's/--//g' , 's/name=name=/name=/g')
。
这里是@CharlesDuffy 答案的一个稍微更稳健的变体。由于后者提供了很好的解释性注释,这里不再给出进一步的解释。
jq -nR '
[inputs | index(": ") as $ix | {(.[:$ix]): .[$ix+2:]}]
| add'
这避免了在 "value" 包含“:”的情况下使用 split
。然而,最好不要假设 space 跟在第一个相关的“:”之后。
另请注意,这里使用 add
而不是 reduce
,只是为了简洁。
对于这类问题,我更愿意使用正则表达式来匹配键和值。否则,我会采用类似于 Charles 的方法。
$ ... | jq -Rn 'reduce (inputs | capture("(?<k>[^:]+):\s*(?<v>.+)")) as {$k, $v} ({}; .[$k] = $v)'
hokay,我正在尝试编写一个脚本,从 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 手册页,我已经阅读哈希的。似乎没有任何意义。我知道我需要有一个 "key"/"value" 如何指定这些?
我只想获取输出并使它看起来漂亮 JSON,这是我正在编写的更大脚本的一部分,以帮助掌握我们在工作中使用的存储库。不过,我完全没有得到 JSON。
编辑:我宁愿不使用包装函数和do/learn正确的方法
所以,首先,没有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
}
值得注意的是,您所有的键都在字符串 :
之前,而值在它们之后——所以我们要逐行读取,根据冒号-space 序列拆分,把前面的当作键,把后面的当作值。
鉴于:
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 -n
将null
视为唯一的直接输入,因此可以在脚本中需要的地方使用input
和inputs
原语。[ inputs ]
读取所有输入行,并将它们放入一个数组中。[ inputs | split(": ")]
将其从字符串数组更改为列表数组——在": "
序列之前和之后都有内容。reduce .[] as $kv ( {}; ... )
启动一个 reducer,初始值为{}
,然后提供.[]
求得的每个值(也就是说,您列表中的每个项目)作为$kv
变量进入该减速器(...
代码),每次替换.
值。
为了 运行 这个用你的 yum 命令作为真正的输入,改变 < <(write_output)
到 < <(yum -v repolist all | grep -B2 -A6 "enabled" | sed 's/[[:space:]]//g' , 's/--//g' , 's/name=name=/name=/g')
。
这里是@CharlesDuffy 答案的一个稍微更稳健的变体。由于后者提供了很好的解释性注释,这里不再给出进一步的解释。
jq -nR '
[inputs | index(": ") as $ix | {(.[:$ix]): .[$ix+2:]}]
| add'
这避免了在 "value" 包含“:”的情况下使用 split
。然而,最好不要假设 space 跟在第一个相关的“:”之后。
另请注意,这里使用 add
而不是 reduce
,只是为了简洁。
对于这类问题,我更愿意使用正则表达式来匹配键和值。否则,我会采用类似于 Charles 的方法。
$ ... | jq -Rn 'reduce (inputs | capture("(?<k>[^:]+):\s*(?<v>.+)")) as {$k, $v} ({}; .[$k] = $v)'