JSON配列のフィールドをbash配列に解析します。

JSON配列のフィールドをbash配列に解析します。

変数に格納されているオブジェクトのリストを含むJSON出力があります。 (私の表現は正確ではないかもしれません)

[
  {
    "item1": "value1",
    "item2": "value2",
    "sub items": [
      {
        "subitem": "subvalue"
      }
    ]
  },
  {
    "item1": "value1_2",
    "item2": "value2_2",
    "sub items_2": [
      {
        "subitem_2": "subvalue_2"
      }
    ]
  }
]

Ubuntu 14.04.1でbashスクリプトを実行するには、配列にitem2のすべての値が必要です。

必要な項目だけでなく、結果全体を配列に入れるいくつかの方法が見つかりました。

答え1

使用:

readarray arr < <(jq '.[].item2' json)
printf '%s\n' "${arr[@]}"

より集中的なアプローチが必要な場合:

readarray -td '' arr

改行やその他の特殊文字を入力するときは、単語の分割を避けてください。

出力:

value2
value2_2

確認する:

一時ファイル名で置換>(command ...)または置換を処理します。<(...)このファイルを書き込んだり読み込んだりすると、バイトは内部コマンドにパイプされます。通常、ファイルのリダイレクトで使用されます。cmd1 2> >(cmd2).seehttp://mywiki.wooledge.org/ProcessSubstitution http://mywiki.wooledge.org/BashFAQ/024

答え2

以下は実際に間違っています。

# BAD: Output line of * is replaced with list of local files; can't deal with whitespace
arr=( $( curl -k "$url" | jq -r '.[].item2' ) )

bash 4.4以降では、最良のオプションを使用できます。

# BEST: Supports bash 4.4+, with failure detection and newlines in data
{ readarray -t -d '' arr && wait "$!"; } < <(
  set -o pipefail
  curl --fail -k "$url" | jq -j '.[].item2 | (., "\u0000")'
)

...bash 4.0では、エラー検出と文字通り改行サポートを犠牲にして簡潔さを得ることができます。

# OK (with bash 4.0), but can't detect failure and doesn't support values with newlines
readarray -t arr < <(curl -k "$url" | jq -r '.[].item2' )

...またはbash 3.x互換性とエラー検出、改行サポートなし:

# OK: Supports bash 3.x; no support for newlines in values, but can detect failures
IFS=$'\n' read -r -d '' -a arr < <(
  set -o pipefail
  curl --fail -k "$url" | jq -r '.[].item2' && printf '\0'
)

...またはbash 3.xの互換性と改行のサポートがありますが、失敗の検出はありません。

# OK: Supports bash 3.x and supports newlines in values; does not detect failures
arr=( )
while IFS= read -r -d '' item; do
  arr+=( "$item" )
done < <(curl --fail -k "$url" | jq -j '.[] | (.item2, "\u0000")')

答え3

jq評価を生成するために使用されるシェル文:

eval "$( jq -r '@sh "arr=( \([.[].item2]) )"' file.json )"

質問のJSON文書が与えられると、呼び出しはjq文字列を生成します。

arr=( 'value2' 'value2_2' )

その後、シェルで評価されます。この文字列を評価すると、arr2つの要素の合計を含む名前付きvalue2配列が生成されますvalue2_2

$ eval "$( jq -r '@sh "arr=( \([.[].item2]) )"' file.json )"
$ printf '"%s"\n' "${arr[@]}"
"value2"
"value2_2"

@shin演算子はjqシェルのデータを正しく引用するように注意を払います。

または、そのarr=( ... )部分を式の外に移動しますjq

eval "arr=( $( jq -r '@sh "\([.[].item2])"' file.json ) )"

jq参照された要素のリストのみが生成され、挿入され評価arr=( ... )されます。

curlコマンドからデータを読み取る必要がある場合は、上記のコマンドで代わりに使用してくださいcurl ... | jq -r ...jq -r ... file.json

答え4

Sputnickのおかげで、次のようになりました。

arr=( $(curl -k https://localhost/api | jq -r '.[].item2') )

私のJSONはAPIの出力です。私がしなければならないのは、ファイルパラメータを削除して|カールの出力をjqにパイプすることだけです。うまく動作し、いくつかのステップを保存します。

関連情報