繁体   English   中英

将使用 jq 解析的数组分配给 Bash 脚本数组

[英]Assigning an Array Parsed With jq to Bash Script Array

我用 jq 解析了一个 json 文件,如下所示:

# cat test.json | jq '.logs' | jq '.[]' | jq '._id' | jq -s

它返回一个这样的数组: [34,235,436,546,.....]

使用 bash 脚本我描述了一个数组:

# declare -a msgIds = ...

这个数组使用()而不是[]所以当我将上面给出的数组传递给这个数组时它不起作用。

([324,32,45..])这会导致问题。 如果我删除jq -s ,则会形成一个只有 1 个成员的数组。

有没有办法解决这个问题?

我们可以通过两种方式解决这个问题。 他们是:

输入字符串:

// test.json
{
    "keys": ["key1","key2","key3"]
}

方法一:

1) 使用jq -r (输出原始字符串,而不是 JSON 文本)。

KEYS=$(jq -r '.keys' test.json)
echo $KEYS
# Output: [ "key1", "key2", "key3" ]

2) 使用@sh (将输入字符串转换为一系列以空格分隔的字符串)。 它从字符串中删除方括号[]、逗号(,)。

KEYS=$(<test.json jq -r '.keys | @sh')
echo $KEYS
# Output: 'key1' 'key2' 'key3'

3) 使用tr从字符串输出中删除单引号。 要删除特定字符,请使用tr的 -d 选项。

KEYS=$((<test.json jq -r '.keys | @sh')| tr -d \') 
echo $KEYS
# Output: key1 key2 key3

4)我们可以通过将字符串输出放在圆括号()中来将逗号分隔的字符串转换为数组。 它也称为复合赋值,我们用一堆值声明数组。

ARRAYNAME=(value1 value2  .... valueN)
#!/bin/bash
KEYS=($((<test.json jq -r '.keys | @sh') | tr -d \'\"))

echo "Array size: " ${#KEYS[@]}
echo "Array elements: "${KEYS[@]}

# Output: 
# Array size:  3
# Array elements: key1 key2 key3

方法二:

1) 使用jq -r得到字符串输出,然后使用tr删除方括号、双引号和逗号等字符。

#!/bin/bash
KEYS=$(jq -r '.keys' test.json  | tr -d '[],"')
echo $KEYS

# Output: key1 key2 key3

2)然后我们可以通过将我们的字符串输出放在圆括号()中来将逗号分隔的字符串转换为数组。

#!/bin/bash
KEYS=($(jq -r '.keys' test.json  | tr -d '[]," '))

echo "Array size: " ${#KEYS[@]}
echo "Array elements: "${KEYS[@]}

# Output:
# Array size:  3
# Array elements: key1 key2 key3

使用jq -r输出字符串“raw”,不带 JSON 格式,并使用@sh格式化程序将结果格式化为字符串以供 shell 使用。 根据 jq 文档:

@sh:

输入已转义,适用于 POSIX shell 的命令行。 如果输入是数组,则输出将是一系列以空格分隔的字符串。

所以可以做例如

msgids=($(<test.json jq -r '.logs[]._id | @sh'))

并得到你想要的结果。

从 jq 常见问题解答( https://github.com/stedolan/jq/wiki/FAQ ):

𝑸:jq 生成的 JSON 文本流如何转换为对应值的 bash 数组?

答:一种选择是使用 mapfile(又名 readarray),例如:

mapfile -t array <<< $(jq -c '.[]' input.json)

另一种可能指示在其他 shell 中做什么的替代方法是在 while 循环中使用 read -r。 以下 bash 脚本使用 JSON 文本填充数组 x。 关键点是 -c 选项的使用,以及while read -r value; do ... done < <(jq .......)使用 bash 惯用语while read -r value; do ... done < <(jq .......) while read -r value; do ... done < <(jq .......)

#!/bin/bash
x=()
while read -r value
do
  x+=("$value")
done < <(jq -c '.[]' input.json)

++ 为了解决这个问题,我们可以使用一个非常简单的方法:

++ 由于我不知道你的输入文件,我正在创建一个文件 input.json ,内容如下:

输入.json:

{
    "keys": ["key1","key2","key3"]
}

++ 使用 jq 从上述文件 input.json 中获取值:

命令: cat input.json | jq -r '.keys | @sh' cat input.json | jq -r '.keys | @sh'

输出:'key1' 'key2' 'key3'

解释: | @sh 删除 [ 和 "

++ 为了删除 ' ' 我们也使用 tr

命令: cat input.json | jq -r '.keys | @sh' | tr -d \\' cat input.json | jq -r '.keys | @sh' | tr -d \\'

说明:使用 tr delete -d 删除 '

++ 要将其存储在 bash 数组中,我们使用 () 和 `` 并打印它:

命令:

KEYS=(`cat input.json | jq -r '.keys | @sh' | tr -d \'`)

打印数组的所有条目: echo "${KEYS[*]}"

要正确解析具有空格、换行符(或任何其他任意字符)的值,只需使用 jq 的@sh过滤器和 bash 的declare -a

json='{"data":["A B", "C\nD", ""]}'
str=$(jq -r '.data | @sh' <<<"$json")
declare -a arr="($str)"    # must be quoted like this
$ declare -p arr
declare -a arr=([0]="A B" [1]=$'C\nD' [2]="")

这正常工作的原因是@sh将生成一个空格分隔的 shell 引用单词列表:

$ echo "$str"
'A B' 'C
D' ''

这正是declare期望数组定义的格式。 不需要while read循环或任何其他预处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM