gpt4 book ai didi

json - bash:遍历由索引选择的 JSON 数组的成员

转载 作者:IT王子 更新时间:2023-10-29 00:38:48 24 4
gpt4 key购买 nike

我正在使用 jq 解析一个 JSON 文件,将一个系列中的每个 JSON 数组提取到一个 shell 数组中。

我当前的代码如下所示:

for ((i = 0; i < ${#nvars[@]}; i++)); do
v1=($(cat $INPUT | jq '."config"[i]."var1"[]'))
echo $v1
done

错误信息:

error: i is not defined

我也换了

v1=($(cat $INPUT | jq '."config"[i]."var1"[]'))

v1=($(cat $INPUT | jq '."config"[$i]."var1"[]'))

还是不行。任何想法?任何帮助表示赞赏!


编辑:示例输入数据

{
"config-vars":[
{
"var1":["v1","v2"],
"var2":""
},
{
"var1":["v3",""],
"var2":"v4"
}
]
}

最佳答案

还有相当大的改进空间。让我们从这里开始:

v1=($(cat $INPUT | jq '."config"[$i]."var1"[]'))

...首先,您实际上不需要使用 cat ;它会降低您的性能,因为它会强制 jq从管道读取而不是直接从输入文件读取。正在运行 jq <"$INPUT"会更健壮(或者更好的是 <"$input" ,以避免使用全大写的名称,这是 shell 内置函数和环境变量的约定保留的名称)。

其次,您需要引用所有变量扩展,包括输入文件名的扩展——否则,只要您的文件名包含空格,您就会遇到错误。

第三,array=( $(stuff) )拆分 stuff 的输出IFS 中的所有字符,并将拆分结果扩展为一系列 glob 表达式(因此,如果输出包含 *.txt,并且您在包含文本文件的目录中运行此脚本,您将在结果数组中获得这些文件的名称)。仅在换行符上拆分意味着您可以正确解析多词字符串,并且在存在 glob 字符的情况下可靠地使用此技术之前,必须禁用 glob 扩展。一种方法是设置 IFS=$'\n'然后运行 ​​set -h在运行此命令之前;另一种方法是将命令的输出重定向到 while read循环(如下所示)。

第四,将字符串替换为代码在任何语言中都是不好的做法——那是(本地等价于)Bobby Tables ,允许那些应该只能更改传递到您的进程的数据的人提供作为可执行代码处理的内容(尽管在这种情况下,作为 jq 脚本,这比在更全功能的语言;不过,这可以允许将额外的数据添加到输出中)。

下一步,一旦你得到 jq要发出以换行符分隔的内容,您根本不需要将其读入数组:您可以迭代从 jq 写入的内容并读入您的 shell,从而防止 shell 需要分配内存来缓冲该内容:

while IFS= read -r; do
echo "read content from jq: $REPLY"
done < <(jq -r --arg i "$i" '.config[$i | tonumber].var1[]' <"$input")

最后 -- 假设您确实想要使用数组。有两种方法可以避免陷阱。一种是设置IFS在赋值之前显式地禁用 glob 扩展:

IFS=$'\n' # split only on newlines
set -f
result=( $(jq -r ... <"$input") )

另一种是用循环赋值给你的数组:

result=( )
while IFS= read -r; do
result+=( "$REPLY" )
done < <(jq -r ... <"$input")

...或者,按照@JohnKugelman 的建议,使用 read -a在一次操作中读取整个数组:

IFS=$'\n' read -r -d '' -a result < <(jq -r ... <"$input")

关于json - bash:遍历由索引选择的 JSON 数组的成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27993448/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com