我有一个大型 JSON 文件,它是对象的对象,我想在对象键之后将其拆分为单独的文件名。是否可以使用 jq 或任何其他现成的工具来实现这一点?
原始 JSON 格式如下
{ "item1": {...}, "item2": {...}, ...}
鉴于此输入,我想生成文件 item1.json、item2.json 等。
这应该给你一个开始:
for f in `cat input.json | jq -r 'keys[]'` ; do
cat input.json | jq ".$f" > $f.json
done
或者当您坚持使用某些人似乎更喜欢的更腼腆的语法时:
for f in $(jq -r 'keys[]') ; do
jq ".[\"$f\"]" < input.json > "$f.json"
done < input.json
这是一个只需要一次调用 jq 的解决方案:
jq -cr 'keys[] as $k | "\($k)\n\(.[$k])"' input.json |
while read -r key ; do
read -r item
printf "%s\n" "$item" > "/tmp/$key.json"
done
将 jq 命令的输出通过管道传输到 awk 可能会更快,例如:
jq -cr 'keys[] as $k | "\($k)\t\(.[$k])"' input.json |
awk -F\\t '{ print $2 > "/tmp/" $1 ".json" }'
当然,如果键名包含不能在文件名中使用的字符,则需要修改这些方法。
是否可以使用 jq或任何其他现成的工具来实现这一点?
这是。xidel也可以非常有效地做到这一点。
让我们假设'input.json':
{
"item1": {
"a": 1
},
"item2": {
"b": 2
},
"item3": {
"c": 3
}
}
低效的 Bash 方法:
for f in $(xidel -s input.json -e '$json()'); do
xidel -s input.json -e '$json("'$f'")' > $f.json
done
对于每个对象键,调用另一个实例xidel
来解析对象。特别是当你有一个非常大的 JSON 时,这非常慢。
有效的file:write()
方法:
xidel -s input.json -e '
$json() ! file:write(
.||".json",
$json(.),
{"method":"json"}
)
'
一次xidel
调用会创建'item{1,2,3}.json'。它们的内容是一个紧凑/缩小的对象,例如{"a": 1}
' item1.json'。
xidel -s input.json -e '
for $x in $json() return
file:write(
concat($x,".json"),
$json($x),
{
"method":"json",
"indent":true()
}
)
'
一次xidel
调用会创建'item{1,2,3}.json'。他们的内容是一个美化的对象(因为{"indent":true()}
),比如......
{
"a": 1
}
...对于'item1.json'。不同的查询(for-loop),相同的结果。
这种方法要快很多!