odi*_*tla 6 linux bash shell json jq
我正在使用jq解析JSON文件,将一系列中的每个JSON数组提取到一个shell数组中.
我当前的代码如下所示:
for ((i = 0; i < ${#nvars[@]}; i++)); do
    v1=($(cat $INPUT | jq '."config"[i]."var1"[]'))
    echo $v1
done
Run Code Online (Sandbox Code Playgroud)
错误信息:
error: i is not defined
Run Code Online (Sandbox Code Playgroud)
我也换了
v1=($(cat $INPUT | jq '."config"[i]."var1"[]'))
Run Code Online (Sandbox Code Playgroud)
同
v1=($(cat $INPUT | jq '."config"[$i]."var1"[]'))
Run Code Online (Sandbox Code Playgroud)
还是行不通.任何的想法?任何帮助表示赞赏!
编辑:示例输入数据
{
    "config-vars":[
        {
            "var1":["v1","v2"],
            "var2":""
        },
        {
            "var1":["v3",""],
            "var2":"v4"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)
    Cha*_*ffy 15
有一点改进的余地.我们从这里开始:
v1=($(cat $INPUT | jq '."config"[$i]."var1"[]'))
Run Code Online (Sandbox Code Playgroud)
......首先,你实际上并不需要使用cat; 它会降低你的性能,因为它会强制jq从管道而不是直接从输入文件中读取.刚运行jq <"$INPUT"会更健壮(或者更好,<"$input"避免使用全大写的名称,这些名称是由shell内置函数和环境变量按惯例保留的).
其次,您需要引用所有变量扩展,包括扩展输入文件的名称 - 否则,只要文件名包含空格,就会出现错误.
三,array=( $(stuff) )拆分的输出stuff上的IFS的所有字符,而分裂的结果作为扩展一系列的水珠表达式(所以如果输出包含*.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")
Run Code Online (Sandbox Code Playgroud)
最后 - 假设您确实想要使用数组.有两种方法可以避免陷阱.一种是IFS在赋值之前显式设置并禁用glob扩展:
IFS=$'\n' # split only on newlines
set -f
result=( $(jq -r ... <"$input") )
Run Code Online (Sandbox Code Playgroud)
另一种是用循环分配给你的数组:
result=( )
while IFS= read -r; do
  result+=( "$REPLY" )
done < <(jq -r ... <"$input")
Run Code Online (Sandbox Code Playgroud)
...或者,正如@JohnKugelman所建议的那样,用于read -a在一次操作中读取整个数组:
IFS=$'\n' read -r -d '' -a result < <(jq -r ... <"$input")
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           13728 次  |  
        
|   最近记录:  |