簡體   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