このファイルが与えられたら:
$ cat fruits.json
[
{ "name": "apple" },
{ "name": "banana\nfofanna" },
{ "name": "my kiwi" }
]
jq
たとえば、配列を埋めるためにシェルがデータとして使用するフルーツ名のリストを取得するためにこれをどのように使用できますか?
fruits
次の配列割り当てと同じです。
$ fruits=(
'apple'
'banana
fofanna'
'my kiwi'
)
$ for f in "${fruits[@]}" ;do echo "<$f>"; done
<apple>
<banana
fofanna>
<my kiwi>
次のいずれも無効です。
$ fruits=( $(jq -r ' .[].name ' fruits.json))
$ fruits=( $(jq -r ' .[].name | @sh ' fruits.json))
$ fruits=( $(jq ' .[].name | @sh ' fruits.json))
答え1
質問の最後の最初の2つの試みは、空白にjq
出力を分割するシェルに依存するため、機能しません。改行は一種の空白なので、データから改行(タブや生の空白を含む)が失われます。
また、これらの試行は文字列データを参照できないため、文字列にファイル名のワイルドカードが含まれている場合は、ファイル名のワイルドカードを取得します。
同様の理由で最後の試みは失敗しましたが、データを正しくデコードできず、エンコードされた改行がそのまま残りました。
組み込み演算子@sh
in を使用してjq
データを参照し、配列割り当てを構成します。
eval "$( jq -r '"fruits=(" + (map(.name)|@sh) + ")"' fruits.json )"
与えられたJSONデータに対して、現在のシェルは次の割り当てを評価して配列を作成しますfruits
。
fruits=('apple' 'banana
fofanna' 'my kiwi')
この声明を評価した後、
$ printf '<%s>\n' "${fruits[@]}"
<apple>
<banana
fofanna>
<my kiwi>
代わりに、追加name
シェル配列の各要素の値:
$ jq -r '"fruits+=(" + (.[].name | @sh) + ")"' fruits.json
fruits+=('apple')
fruits+=('banana
fofanna')
fruits+=('my kiwi')
$ unset -v fruits
$ eval "$(jq -r '"fruits+=(" + (.[].name | @sh) + ")"' fruits.json)"
$ printf '<%s>\n' "${fruits[@]}"
<apple>
<banana
fofanna>
<my kiwi>
答え2
ZSHにどのシェルを使用するかについては言及していません。
% fru=( ${(fQg::)"$(jq '.[].name' ~/tmp/fru)"} )
% for f in $fru; printf '<%s>\n' $f
<apple>
<banana
fofanna>
<my kiwi>
% =echo -n "<${fru[2]}>" | od -bc
0000000 074 142 141 156 141 156 141 012 146 157 146 141 156 156 141 076
< b a n a n a \n f o f a n n a >
0000020
jq
呼び出しを実行し、f
結果を改行に分割し、出力から文字列に残った引用符を削除しますQ
。jq
g::
補間を実行するために組み込まれたエコーのように動作します。\n
入力の文字列に。
答え3
@Kusalananda、@roaima、@StéphaneChazelasの回答とコメントに基づいて上記のコメントに記載されている同様の質問、私は次を見つけることができました:
list=$( jq -r ' .[].name | @sh ' fruits.json ) || exit 1
eval "fruits=( $list )" || exit 1
printf "<%s>\n" "${fruits[@]}"