私はJQ
クイズデータベースからいくつかのJSONを取得するために使用しており、結果を解析したいと思います。以下のように結果配列を Bash に保存しようとしていますが、型が Bash スタイルではなく JavaScript/Python で使用される括弧型です。
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"
]
}
]
}
答え1
jq
結果を1行ずつ出力します。次に、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
[[...]]
演算子==
の内部にはいいえ文字列恒等演算子は次のとおりです。パターンマッチングオペレーター。
- 最初のテストは単純な文字列比較です。
- 2番目のテストでは、CVS文字列に誤った答えが含まれていることを確認します。含む回答二重引用符で囲む
答え2
ズームローマ・ペレクレスト答え(今のように):
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
答え3
設定された目標に応じてcorrect_answer
「Bash配列に合計を含めたいと思いますincorrect_answers
。」結合された値の配列が得られると予想されます。
2つの異なるコマンドを実行する代わりに、jq
結合シーケンス全体をjq
単一の式にまとめることができます。
~のため一言配列項目:
$ declare -a answers=($(jq -r '[.results[0].correct_answer] + .results[0].incorrect_answers | @sh' <<<"$quiz"))
@sh
:入力は、POSIXシェルのコマンドラインで使用するためにエスケープされます。入力が配列の場合、出力はスペースで区切られた一連の文字列です。
結果:
$ echo "${answers[2]}"
'BBC'
$ echo "${answers[0]}"
'Amazon'
$ echo "${answers[1]}"
'Netflix'
$ echo "${answers[@]}"
'Amazon' 'Netflix' 'BBC' 'CCTV'
スペースを含む項目(例:の項目.results[1]
)を処理するには、次の方法readarray
と@json
オプションを使用します。
$ readarray -t answers < <(jq -r '[.results[1].correct_answer] + .results[1].incorrect_answers | .[] |@json' <<<"$quiz")
結果:
$ echo "${answers[1]}"
"30 lbs"
$ echo "${answers[0]}"
"60 lbs"
$ echo "${answers[@]}"
"60 lbs" "30 lbs" "50 lbs" "70 lbs"
$ echo "${answers[2]}"
"50 lbs"
答え4
results
配列の各要素を繰り返し、correct_answer
各要素の値をシェル変数に割り当て、incorrect_answers
その値を次の配列変数に割り当てるとしますbash
。
#!/bin/bash
data=file.json
unset results
eval "$( jq -r '@sh "results=\(.results|length)"' "$data" )"
if [ -z "$results" ]; then
echo 'Failed to parse number of results' >&2
exit 1
fi
for (( i = 0; i < results; ++i )); do
unset correct_answer
unset incorrect_answers
eval "$(
jq -r --argjson i "$i" '
.results[$i] |
@sh "correct_answer=\(.correct_answer)",
@sh "incorrect_answers+=(\(.incorrect_answers[]))"' "$data"
)"
printf 'The correct answer for question %d was "%s"\n' \
"$((i+1))" "$correct_answer"
echo 'The question had the following incorrect answers:'
printf '\t"%s"\n' "${incorrect_answers[@]}"
done
質問のデータが与えられると、以下が出力されます。
The correct answer for question 1 was "Amazon"
The question had the following incorrect answers:
"Netflix"
"BBC"
"CCTV"
The correct answer for question 2 was "60 lbs"
The question had the following incorrect answers:
"30 lbs"
"50 lbs"
"70 lbs"
The correct answer for question 3 was "True"
The question had the following incorrect answers:
"False"
各反復では、ツールはJSONドキュメントから配列内の特定の要素をjq
抽出するために使用されます。results
データをシェル割り当てセットにフォーマットします。たとえば、$i
1 の場合、文が生成されます。
correct_answer='60 lbs'
incorrect_answers+=('30 lbs')
incorrect_answers+=('50 lbs')
incorrect_answers+=('70 lbs')
その後、シェルはこれらの文を評価して変数correct_answer
と配列を生成しますincorrect_answers
。