mic*_*_65 19 bash json docker jq
我试图从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
Run Code Online (Sandbox Code Playgroud)
输出来自docker stats命令,我的最终目标是将自定义指标发布到aws cloudwatch.我想将此字符串格式化为json.
{
"CONTAINER":"nginx_container",
"CPU%":"0.02%",
....
}
Run Code Online (Sandbox Code Playgroud)
我之前使用过jq命令,看起来它应该在这种情况下运行良好,但我还没有找到一个好的解决方案.除了硬编码变量名和使用sed或awk索引.然后从头开始创建一个json.任何建议,将不胜感激.谢谢.
Cha*_*ffy 42
对于以下所有内容,假设您的内容位于名为的shell变量中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'
Run Code Online (Sandbox Code Playgroud)
# 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"
Run Code Online (Sandbox Code Playgroud)
这需要非常新的(可能是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
,我们将这些对组合成包含这些键和值的对象.这将使用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"
Run Code Online (Sandbox Code Playgroud)
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' \
<<<'{}'
Run Code Online (Sandbox Code Playgroud)
...将每个键和值传递到带外(这样它被视为文字字符串而不是解析为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"
}
Run Code Online (Sandbox Code Playgroud)
简而言之:因为它保证生成有效的JSON作为输出.
考虑以下作为一个破坏更天真的方法的例子:
s='key ending in a backslash\
value "with quotes"'
Run Code Online (Sandbox Code Playgroud)
当然,这些是意想不到的情况,但jq
知道如何处理它们:
{
"key ending in a backslash\\": "value \"with quotes\""
}
Run Code Online (Sandbox Code Playgroud)
...而不理解JSON字符串的实现很容易最终发出:
{
"key ending in a backslash\": "value "with quotes""
}
Run Code Online (Sandbox Code Playgroud)
Jim*_*Jim 13
我知道这是一篇旧帖子,但您寻求的工具称为jo
:https : //github.com/jpmens/jo
一个快速简单的例子:
$ jo my_variable="simple"
{"my_variable":"simple"}
Run Code Online (Sandbox Code Playgroud)
稍微复杂一点
$ jo -p name=jo n=17 parser=false
{
"name": "jo",
"n": 17,
"parser": false
}
Run Code Online (Sandbox Code Playgroud)
添加数组
$ jo -p name=jo n=17 parser=false my_array=$(jo -a {1..5})
{
"name": "jo",
"n": 17,
"parser": false,
"my_array": [
1,
2,
3,
4,
5
]
}
Run Code Online (Sandbox Code Playgroud)
我用 jo 制作了一些非常复杂的东西,好处是你不必担心滚动你自己的解决方案,担心制作无效的 json 的可能性。
你可以先让docker给你JSON数据
docker stats --format "{{json .}}"
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅:https : //docs.docker.com/config/formatting/
归档时间: |
|
查看次数: |
21331 次 |
最近记录: |