先决条件
对于以下所有内容,假设您的内容位于名为 s 的 shell 变量中:
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'
什么(现代 jq)
# 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"
如何(现代 jq)
这需要非常新的(可能是 1.5?)jq 才能工作,并且是一个密集的代码块。分解:
- 使用
-n 可防止jq 自行读取标准输入,从而使input 和inputs 可以读取整个输入流——前者读取单行,后者读取读取所有剩余的行。 (-R,对于原始输入,会导致读取文本行而不是 JSON 对象)。
- 使用
[$keys, $vals] | transpose[],我们生成[key, value] 对(在Python 术语中,压缩两个列表)。
- 使用
{key:.[0],value:.[1]},我们将每个[key, value] 对变成{"key": key, "value": value} 形式的对象
- 通过
from_entries,我们将这些对组合成包含这些键和值的对象。
什么(shell 辅助)
这将适用于比上述更旧的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"
如何(shell 辅助)
上面调用的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 作为输出。
将以下示例视为打破更幼稚方法的示例:
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""
}