我有一个json响应,如下所示:
[
{"id":10,
"list_file":["/var/a.txt",
"/dev/b.txt"]}
]
我需要提取list_file的值并将其作为数组存储在shell变量中。我尝试循环并读取值。
#!/bin/bash
x=()
while read -r value
do
#echo "$value"
x+=("$value")
done < <(jq -r '.[] | .list_file' input.json)
但是数组中提取的值也包含引号,括号和逗号。
[
"/var/a.txt",
"/dev/b.txt"
]
请你帮我修改代码,以便数组只包含条目/var/a.txt和/dev/b.txt。此外,我尝试了readarray和map,但它们无法在Mac Osx上运行。任何帮助都会非常感激。
答案 0 :(得分:3)
您可以将@tsv
字符串格式化程序与--raw-output
/-r
选项结合使用,并将输出拆分为选项卡上的bash
数组:
$ IFS=$'\t'
$ x=($(jq -r '.[] | .list_file | @tsv' input.json))
$ for xx in "${x[@]}"; do echo "$xx"; done
/var/a.txt
/dev/b.txt
对于-r
,将删除外部引号(对于使jq
过滤器与非基于JSON的系统进行对话非常有用),@tsv
将输出一个数组作为一系列标签 - 分隔的字符串(标签,换行符等将被转义)。
或者,您使用@sh
过滤器将数组输出为一系列以空格分隔的字符串。但是,要解释此类输出,您必须eval
使用它:
$ eval "x=($(jq -r '.[] | .list_file | @sh' input.json))"
答案 1 :(得分:3)
为了正确处理所有值,您需要使用declare
命令将jq
的输出合并到数组赋值中。
这里有一些输入,需要担心一些角落情况:空格,换行符和全局字符。
$ cat input.json
[
{"id":10,
"list_file":[
"/var/a b.txt",
"/dev/c\nd.txt",
"*"]}
]
jq
命令,用于提取和输出正确引用的字符串以供shell使用:
$ $ jq -r '.[] | .list_file[] | @sh' input.json
'/var/a b.txt'
'/dev/c
d.txt'
'*'
可以使用输出的shell命令:
$ declare -a "x=($(jq -r '.[] | .list_file[] | @sh' input.json))"
证明它运作正常:
$ printf '==%s==\n' "${x[@]}"
==/var/a b.txt==
==/dev/c
d.txt==
==*==
答案 2 :(得分:0)
在Mac上,安装带有readarray
的bash很容易(例如使用自制软件:brew install bash
),所以在下面我会假设它和&#39; ll #39;可用,但您也可以使用while read -r value
技术逐行读取值。 (这些面向行的方法的一个优点是不需要使用IFS。)
对于手头的问题,可能会出现这样的情况:保留特殊字符的JSON表示形式会更好,例如&#34; \ n&#34;对于NEWLINE,&#34; \ u0000&#34;对于NUL等,无论如何,使用-r
的一般替代方法是使用-c
命令行选项,如下所示:
$ readarray -t x < <(jq -n -c '("\u0001\nb", "c\td", "e\u0000f")'
| sed -e 's/^\"//' -e 's/\"$//' )
$ printf ":%s:\n" "${x[@]}"
:\u0001\nb:
:c\td:
:e\u0000f: