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
从管道中读取,而不是直接从输入文件中读取。只要运行
jq
jq
就可以一次性提取结构,因此整个循环是多余的。如果输入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 ‘.[]‘)