bash:迭代索引选择的JSON数组的成员
我使用bash:迭代索引选择的JSON数组的成员,json,linux,bash,shell,jq,Json,Linux,Bash,Shell,Jq,我使用jq解析一个JSON文件,将一系列中的每个JSON数组提取到一个shell数组中 我当前的代码如下所示: for ((i = 0; i < ${#nvars[@]}; i++)); do v1=($(cat $INPUT | jq '."config"[i]."var1"[]')) echo $v1 done 我也换了 v1=($(cat $INPUT | jq '."config"[i]."var1"[]')) 与 仍然不起作用。有什么想法吗?感谢您的帮助 编
jq
解析一个JSON文件,将一系列中的每个JSON数组提取到一个shell数组中
我当前的代码如下所示:
for ((i = 0; i < ${#nvars[@]}; i++)); do
v1=($(cat $INPUT | jq '."config"[i]."var1"[]'))
echo $v1
done
我也换了
v1=($(cat $INPUT | jq '."config"[i]."var1"[]'))
与
仍然不起作用。有什么想法吗?感谢您的帮助
编辑:示例输入数据
{
"config-vars":[
{
"var1":["v1","v2"],
"var2":""
},
{
"var1":["v3",""],
"var2":"v4"
}
]
}
变量不在单引号内插值。改为使用双引号,并删除现有引号
v1=($(cat $INPUT | jq ".config[$i].var1[]"))
或者使用--arg
选项,然后可以使用单引号
v1=($(cat $INPUT | jq --arg i "$i" '.config[$i].var1[]'))
您还可以修复cat的无用用法:
v1=($(jq ".config[$i].var1[]" "$INPUT"))
另外,请参阅@CharlesDuffy的答案,以获得关于为什么这样分配给数组是不安全的详细解释。还有相当大的改进空间。让我们从这里开始:
v1=($(cat $INPUT | jq '."config"[$i]."var1"[]'))
…首先,您实际上不需要使用
cat
;这会降低性能,因为它强制jq
从管道中读取,而不是直接从输入文件中读取。只要运行jqjq
就可以一次性提取结构,因此整个循环是多余的。如果输入JSON包含的记录多于nvars
中的值,请使用索引进行切分
jq -r '."config-vars"[]."var1"' "$INPUT" |
head -n "${#nvars[@]}" # If you need just the #nvars first values
如果您已经将某些JSON的结果存储到名为$MY_VAR的变量中:
while IFS= read -r; do
echo “$REPLY”
done < <(echo $MY_VAR | jq -r ‘.[]‘)
而IFS=read-r;做
回显“$REPLY”
谢谢你的帮助。还有一个问题,如果我有'config vars'而不是'config',我该怎么办?我想这就是为什么最初使用单引号的原因。非常感谢!试试:[\“config vars\”][$i]
。这不是一个坏方法,但是可以告诉jq
更有用——它有一种输出以换行分隔的模式,允许比在任何IFS字符上拆分更健壮的操作。用于修改的道具建议使用--arg code>;我刚刚对此进行了评论,并看到了它。这里还有一个问题——如果jq
发出*
,它将被替换为结果数组中本地目录中的文件名列表。Hello@CharlesDuffy,我尝试了nvars=($(jq--arg I“$I”.“config vars”[$I]。“$INPUT”))
但获取错误:jq:error:无法使用字符串为数组编制索引
。我做错什么了吗?谢谢@odieatla,您要传递的i
的值是多少?@odieatla,…此外,如果您的问题包含与查询所需使用的格式相同的样本数据,这将非常有用。@odieatla,…此外,使用-r
(-原始输出
)是一个好主意;否则,jq的输出将包含诸如引号之类的字符,shell在分词过程中无法正确解析这些字符,而是将其视为文字数据。@odieatla,找到了一个解决方案--在中记录,现在在我的答案中进行了修改;在jq查询中使用$i|tonumber
将值转换为整数。我的首选解决方案,虽然它的相关性取决于脚本的控制流:each_obj(){local cmd=“$1”json_arr=“$2”len i;len=$(jq'length'@Shane),但我建议将其反转一点:json_arr=“$1”;shift
,然后您可以使用“$@”
通过使用$cmd
运行包含所有其他参数的命令,而不冒出现问题的风险。
while IFS= read -r; do
echo "read content from jq: $REPLY"
done < <(jq -r --arg i "$i" '.config[$i | tonumber].var1[]' <"$input")
IFS=$'\n' # split only on newlines
set -f
result=( $(jq -r ... <"$input") )
result=( )
while IFS= read -r; do
result+=( "$REPLY" )
done < <(jq -r ... <"$input")
IFS=$'\n' read -r -d '' -a result < <(jq -r ... <"$input")
jq -r '."config-vars"[]."var1"' "$INPUT" |
head -n "${#nvars[@]}" # If you need just the #nvars first values
while IFS= read -r; do
echo “$REPLY”
done < <(echo $MY_VAR | jq -r ‘.[]‘)