Bash

將 JSON 數組轉換為 Bash

  • July 23, 2021

我正在使用JQ從測驗數據庫中獲取一些 JSON,並且我想解析結果。我正在嘗試將結果數組保存在 Bash 中,如下所示,但格式是 JavaScript/Python 中使用的帶有方括號而不是 Bash 樣式的格式。

quiz=$(curl -s https://opentdb.com/api.php?amount=3)
answers=$(echo $quiz | jq '[ .results][0][0].incorrect_answers')
correct=$(echo $quiz | jq '[ .results][0][0].correct_answer')
answers+=( $correct )

答案的範例如下:

[ "Excitement", "Aggression", "Exhaustion" ]

由於格式錯誤,永遠不會將正確答案推送到數組中。

如何轉換上述格式的數組,以便在我的腳本中將其解釋為數組。

輸出範例curl (這不是硬編碼,問題和答案每次都不同)

{
 "response_code": 0,
 "results": [
   {
     "category": "Entertainment: Television",
     "type": "multiple",
     "difficulty": "easy",
     "question": "Which company has exclusive rights to air episodes of the "The Grand Tour"?",
     "correct_answer": "Amazon",
     "incorrect_answers": [
       "Netflix",
       "BBC",
       "CCTV"
     ]
   },
   {
     "category": "Celebrities",
     "type": "multiple",
     "difficulty": "medium",
     "question": "How much weight did Chris Pratt lose for his role as Star-Lord in "Guardians of the Galaxy"?",
     "correct_answer": "60 lbs",
     "incorrect_answers": [
       "30 lbs",
       "50 lbs",
       "70 lbs"
     ]
   },
   {
     "category": "Animals",
     "type": "boolean",
     "difficulty": "easy",
     "question": "The Killer Whale is considered a type of dolphin.",
     "correct_answer": "True",
     "incorrect_answers": [
       "False"
     ]
   }
 ]
}

我會jq逐行輸出結果。然後使用 bashmapfile命令將行讀入數組

mapfile -t correct < <(jq -r '.results[] | .correct_answer' <<<"$quiz")
declare -p correct
declare -a correct=([0]="Amazon" [1]="60 lbs" [2]="True")

對於不正確的答案,由於 bash 沒有多維數組,我可以jq將不正確答案的數組輸出為 CSV:

mapfile -t incorrect < <(jq -r '.results[] | .incorrect_answers | @csv' <<<"$quiz")
declare -p incorrect
declare -a incorrect=([0]="\"Netflix\",\"BBC\",\"CCTV\"" [1]="\"30 lbs\",\"50 lbs\",\"70 lbs\"" [2]="\"False\"")

然後:

$ echo "q $i: ans=${correct[i]}; wrong=${incorrect[i]}"
q 1: ans=60 lbs; wrong="30 lbs","50 lbs","70 lbs"

文件:


假設您正在與使用者互動:

i=0
read -p "Answer to question $i: " answer

if [[ $answer == "${correct[i]}" ]]; then
   echo Correct
elif [[ ${incorrect[i]} == *"\"$answer\""* ]]; then
   echo Incorrect
else
   echo Invalid answer
fi

請記住,內部運算符[[...]]不是字元串相等運算符,它是模式匹配運算符。==

  • 第一個測試是簡單的字元串比較
  • 第二個測試查看包含不正確答案的 CVS 字元串是否包含**雙引號中的答案

擴展@ RomanPerekhrest的答案(現在就去投票吧):

mapfile -t answers < <(jq -r '.results[] | [.correct_answer] + .incorrect_answers | @sh' <<<"$quiz")
declare -p answers
declare -a answers=([0]="'Amazon' 'Netflix' 'BBC' 'CCTV'" [1]="'60 lbs' '30 lbs' '50 lbs' '70 lbs'" [2]="'True' 'False'")

然後,你可以使用這樣的東西

for i in "${!answers[@]}"; do
   declare -a "this_answers=( ${answers[i]} )"
   echo $i
   printf " > %s\n" "${this_answers[@]}"
done
0
> Amazon
> Netflix
> BBC
> CCTV
1
> 60 lbs
> 30 lbs
> 50 lbs
> 70 lbs
2
> True
> False

引用自:https://unix.stackexchange.com/questions/553445