我有一个这样的json
{
"outer1": {
"outer2": {
"outer3": {
"key1": "value1",
"key2": "value2"
}
},
"outer4": {
"key1": "value1",
"key2": "value2"
}
}
}
我希望输出是
[outer1.outer2.outer3]
key1 = value1
key2 = value2
[outer1.outer2.outer4]
key1 = value1
key2 = value2
我尝试了
jq -r 'to_entries|map("\(.key)=\(.value|tostring)")|.[]' test.json
但这不是我想要的
假设您的输入如下所示:
{
"outer1": {
"outer2": {
"outer3": {
"key1": "value1",
"key2": "value2"
},
"outer4": {
"key1": "value1",
"key2": "value2"
}
}
}
}
您可以使用
--stream
选项将输入读取为路径值对流。例如:
jq --stream -n '
reduce (inputs | select(has(1))) as [$path, $val] ({};
.[$path[:-1] | join(".")][$path[-1]] = $val
)
'
{
"outer1.outer2.outer3": {
"key1": "value1",
"key2": "value2"
},
"outer1.outer2.outer4": {
"key1": "value1",
"key2": "value2"
}
}
接下来,根据您的需要格式化此 JSON。例如,对两个级别都使用
to_entries
:
jq --stream -nr '
reduce (inputs | select(has(1))) as [$path, $val] ({};
.[$path[:-1] | join(".")][$path[-1]] = $val
)
| to_entries[] | "[\(.key)]", (
.value | to_entries[] | "\(.key) = \(.value)"
), ""
'
[outer1.outer2.outer3]
key1 = value1
key2 = value2
[outer1.outer2.outer4]
key1 = value1
key2 = value2
或者,将这两个步骤组合成一个
foreach
迭代,并使用滑动上下文窗口作为状态:
jq --stream -nr '
foreach (inputs | select(has(1))) as [$path, $val] ([];
[last, ($path[:-1] | join("."))];
(select(first != last) | "\n[\(last)]"), "\($path[-1]) = \($val)"
)
'
我的看法是这样的:
. as $data
| [ path(.. | scalars) ]
| map( . as $p | { prefix: $p[0:-1]|join("."), key: $p[-1], value: $data | getpath($p) })
| group_by(.prefix)[]
| "[\(first.prefix)]", (.[] | "\(.key)=\(.value)")
基本上:
["outer1","outer2","outer3","key1"]
)outer1.outer2.outer3
)、键(key1
)和实际值(value1
)如果您尝试生成 TOML 编码文档,还可以考虑使用 kislyuk/yq,它是一个用于处理(YAML、XML 和)TOML 文档的
jq
包装器。 TOML 处理器称为 tomlq
,它在 TOML 和 JSON 之间进行转码,以便可以直接应用 jq
过滤器。不过,对于您的用例,过滤器只需要发出变量的内容,该变量使用 jq 的 --argfile
选项填充 JSON 输入文件的内容(因为从 stdin
读取和直接文件参数预计会是 TOML 编码的,因此使用 -n
)。最终,-t
选项将(最终)JSON 文档(返回)转换为 TOML。输出与您期望的输出略有不同,但如果您的目标是生成 TOML 文档,您可以受益于 tomlq
自动提供有效且格式良好的结构。
tomlq -n -t '$f' --argfile f file.json
[outer1.outer2]
[outer1.outer2.outer3]
key1 = "value1"
key2 = "value2"
[outer1.outer2.outer4]
key1 = "value1"
key2 = "value2"