我试图从bash中的字符串创建一个json对象。字符串如下。
CONTAINER|CPU%|MEMUSAGE/LIMIT|MEM%|NETI/O|BLOCKI/O|PIDS nginx_container|0.02%|25.09MiB/15.26GiB|0.16%|0B/0B|22.09MB/4.096kB|0
输出来自docker stats命令,我的最终目标是将自定义指标发布到AWS CloudWatch。我想将此字符串格式化为json。
{ "CONTAINER":"nginx_container", "CPU%":"0.02%", .... }
我以前使用过jq命令,似乎在这种情况下应该可以正常工作,但是我还没有想出一个好的解决方案。除了使用sed或awk对变量名进行硬编码和索引编制之外。然后从头开始创建一个json。任何建议,将不胜感激。谢谢。
对于以下所有内容,假定您的内容位于名为的shell变量中s:
s
s='CONTAINER|CPU%|MEMUSAGE/LIMIT|MEM%|NETI/O|BLOCKI/O|PIDS nginx_container|0.02%|25.09MiB/15.26GiB|0.16%|0B/0B|22.09MB/4.096kB|0'
# thanks to @JeffMercado and @chepner for refinements, see comments jq -Rn ' ( input | split("|") ) as $keys | ( inputs | split("|") ) as $vals | [[$keys, $vals] | transpose[] | {key:.[0],value:.[1]}] | from_entries ' <<<"$s"
这需要非常新的(可能是1.5?)jq才能工作,并且是一堆密集的代码。分解:
jq
-n
input
inputs
-R
[$keys, $vals] | transpose[]
[key, value]
{key:.[0],value:.[1]}
{"key": key, "value": value}
from_entries
这jq将比上述版本更旧,并且在本地jq解决方案可能更难以解决的情况下是一种易于采用的方法:
{ IFS='|' read -r -a keys # read first line into an array of strings ## read each subsequent line into an array named "values" while IFS='|' read -r -a values; do # setup: positional arguments to pass in literal variables, query with code jq_args=( ) jq_query='.' # copy values into the arguments, reference them from the generated code for idx in "${!values[@]}"; do [[ ${keys[$idx]} ]] || continue # skip values with no corresponding key jq_args+=( --arg "key$idx" "${keys[$idx]}" ) jq_args+=( --arg "value$idx" "${values[$idx]}" ) jq_query+=" | .[\$key${idx}]=\$value${idx}" done # run the generated command jq "${jq_args[@]}" "$jq_query" <<<'{}' done } <<<"$s"
jq上面调用的命令类似于:
jq --arg key0 'CONTAINER' \ --arg value0 'nginx_container' \ --arg key1 'CPU%' \ --arg value1 '0.0.2%' \ --arg key2 'MEMUSAGE/LIMIT' \ --arg value2 '25.09MiB/15.26GiB' \ '. | .[$key0]=$value0 | .[$key1]=$value1 | .[$key2]=$value2' \ <<<'{}'
…将每个键和值带外传递(这样就将其视为文字字符串而不是解析为JSON),然后分别引用它们。
以上任何一种都会发出:
{ "CONTAINER": "nginx_container", "CPU%": "0.02%", "MEMUSAGE/LIMIT": "25.09MiB/15.26GiB", "MEM%": "0.16%", "NETI/O": "0B/0B", "BLOCKI/O": "22.09MB/4.096kB", "PIDS": "0" }
简而言之: 因为可以保证生成有效的JSON作为output 。
考虑以下示例,该示例将打破更多幼稚的方法:
s='key ending in a backslash\ value "with quotes"'
当然,这些是意外情况,但是jq知道如何处理它们:
{ "key ending in a backslash\\": "value \"with quotes\"" }
…而一个不理解JSON字符串的实现很容易最终发出:
{ "key ending in a backslash\": "value "with quotes"" }