2014-11-03 24 views
9

Ho uno script Bash. Ottiene i dati in JSON. Ho bisogno di convertire l'array JSON in un array Bash.Conversione di un array JSON in un array Bash

Esempio

{ 
    "SALUTATION": "Hello world", 
    "SOMETHING": "bla bla bla Mr. Freeman" 
} 

In Bash voglio ottenere un valore come questo echo ${arr[SOMETHING]}.

+0

cerco usare 'JQ -r' .param_name'' , ma il suo lavoro solo se ci conosci il nome del parametro – Evgenii

+1

Se il tuo script riceve JSON arbitrario, ciò potrebbe essere impossibile da fare in puro bash. – helpermethod

risposta

15

Se volete chiave e il valore, e sulla base How do i convert a json object to key=value format in JQ, si può fare:

$ jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" file 
SALUTATION=Hello world 
SOMETHING=bla bla bla Mr. Freeman 

In maniera più generale, è possibile memorizzare i valori in un array myarray[key] = value come questo, semplicemente fornendo jq a la while con l'while ... do; ... done < <(command) sintassi:

declare -A myarray 
while IFS="=" read -r key value 
do 
    myarray[$key]="$value" 
done < <(jq -r "to_entries|map(\"\(.key)=\(.value)\")|.[]" file) 

E poi è possibile scorrere i valori di questo tipo:

for key in "${!myarray[@]}" 
do 
    echo "$key = ${myarray[$key]}" 
done 

Per questo dato input, restituisce: domanda

SALUTATION = Hello world 
SOMETHING = bla bla bla Mr. Freeman 
+1

Ha appena preso l'elemento principale e l'ha aggiunto all'array. Non è ricorsivo. – PhoenixNoor

+0

@PhoenixNoor, per favore guarda la mia risposta in modo ricorsivo: https://stackoverflow.com/a/47026579/720323 – HelpNeeder

4

del PO in realtà descrive gli oggetti, contro gli array.

Per essere sicuri che aiutiamo altre persone che arrivano che sono effettivamente in cerca di aiuto con gli array JSON, tuttavia, vale la pena coprirli esplicitamente.


Per il caso di sicurezza-ish in cui le stringhe non possono contenere ritorni a capo (e quando bash 4.0 o più recente è in uso), questo funziona:

str='["Hello world", "bla bla bla Mr. Freeman"]' 
readarray -t array <<<"$(jq -r '.[]' <<<"$str")" 

per supportare le versioni precedenti di bash, e stringhe con a capo, abbiamo un po 'più elaborato, utilizzando un flusso NUL delimitato per leggere da jq:

str='["Hello world", "bla bla bla Mr. Freeman", "this is\ntwo lines"]' 
array=() 
while IFS= read -r -d '' line; do 
    array+=("$line") 
done < <(jq -j '.[] | (. + "\u0000")') 
1

Ecco come si può fare in modo ricorsivo:

#!/bin/bash 

SOURCE="$PWD" 
SETTINGS_FILE="$SOURCE/settings.json" 
SETTINGS_JSON=`cat "$SETTINGS_FILE"` 

declare -A SETTINGS 

function get_settings() { 
    local PARAMS="$#" 
    local JSON=`jq -r "to_entries|map(\"\(.key)=\(.value|tostring)\")|.[]" <<< "$1"` 
    local KEYS='' 

    if [ $# -gt 1 ]; then 
     KEYS="$2" 
    fi 

    while read -r PAIR; do 
     local KEY='' 

     if [ -z "$PAIR" ]; then 
      break 
     fi 

     IFS== read PAIR_KEY PAIR_VALUE <<< "$PAIR" 

     if [ -z "$KEYS" ]; then 
      KEY="$PAIR_KEY" 
     else 
      KEY="$KEYS:$PAIR_KEY" 
     fi 

     if jq -e . >/dev/null 2>&1 <<< "$PAIR_VALUE"; then 
      get_settings "$PAIR_VALUE" "$KEY" 
     else 
      SETTINGS["$KEY"]="$PAIR_VALUE" 
     fi 
    done <<< "$JSON" 
} 

chiamarlo:

get_settings "$SETTINGS_JSON" 

La matrice sarà letta in questo modo:

${SETTINGS[grandparent:parent:child]}