Преобразование массива JSON в Bash

Вы можете использовать

pass=$(openssl des3 -d -salt -in credential.des3)

(без указания выходного файла)

Но проблема в том, что вы запускаете скрипт из cron. Хотя вы можете организовать передачу некоторого фрагмента данных из cronв сценарий через переменную среды, нет простого способа передать этот пароль в cronбез сохранения его в файловой системе (в файле crontab., скорее всего ).

Чтобы открытый пароль не попадал в постоянное хранилище, вы можете организовать его хранение в tmpfsфайловой системе (в Linux ). Вы можете смонтировать один с mount -t tmpfs tmpfs /path/to/mount/pointили с эквивалентом в fstab. Также есть вероятность, что в вашей системе уже есть /tmpс использованием tmpfs.

Другим альтернативным вариантом может быть сценарий, содержащий незашифрованный пароль, работающий непрерывно и использующий sleepдля выполнения фактической работы в соответствующее время. Хотя в этом случае, если скрипт выйдет из строя, он не будет перезапущен автоматически (, и вам все равно придется вводить пароль вручную, чтобы перезапустить его ).

Обратите внимание, что в любом случае любые секреты, которые у вас есть в памяти, могут быть записаны для замены, если они у вас есть. (По этой причине необходимо использовать зашифрованный обмен.)

0
21.11.2019, 22:54
3 ответа

Я бы заставил jqвывести строку результатов -мудро. Затем используйте команду bash mapfileдля чтения строк в массив

.
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 неверные ответы ответ в двойных кавычках
5
28.01.2020, 02:13

Расширение @ РоманПерехрест ответ (проголосуйте за него сейчас):

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
2
28.01.2020, 02:13

Поскольку этот вопрос засел у меня в голове, небольшой скрипт для запуска игры:

#!/usr/bin/env bash

main() {
    local -a questions
    mapfile -t questions < <(
        get_quiz |
        jq -r '.results[] | [.question] + [.correct_answer] +.incorrect_answers | @sh'
    )

    for i in "${!questions[@]}"; do
        local -a q="( ${questions[i]} )"
        question $((i+1)) "${q[@]}"
    done
}

question() {
    local num=$1 question=$2 correct=$3
    local -a answers=("${@:3}")

    # shuffle the answers
    mapfile -t answers < <(printf "%s\n" "${answers[@]}" | sort -R)

    echo
    echo "Question #$num"
    PS3="${question//&quot;/\'} "

    select answer in "${answers[@]}"; do
        if [[ $answer == "$correct" ]]; then
            echo "Correct"
            break
        fi
        echo "Incorrect"
    done
}

get_quiz() {
    # this is where you'd do your curl call, but 
    # for now, the sample data is printed.
    cat << 'JSON'
    {
      "response_code": 0,
      "results": [
        {
          "category": "Entertainment: Television",
          "type": "multiple",
          "difficulty": "easy",
          "question": "Which company has exclusive rights to air episodes of the &quot;The Grand Tour&quot;?",
          "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 &quot;Guardians of the Galaxy&quot;?",
          "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"
          ]
        }
      ]
    }
JSON
}

main
1
28.01.2020, 02:13

Теги

Похожие вопросы