スペースを考慮してjqを使用して情報をシェルに返すにはどうすればよいですか?

スペースを考慮してjqを使用して情報をシェルに返すにはどうすればよいですか?

このファイルが与えられたら:

$ 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出力を分割するシェルに依存するため、機能しません。改行は一種の空白なので、データから改行(タブや生の空白を含む)が失われます。

また、これらの試行は文字列データを参照できないため、文字列にファイル名のワイルドカードが含まれている場合は、ファイル名のワイルドカードを取得します。

同様の理由で最後の試みは失敗しましたが、データを正しくデコードできず、エンコードされた改行がそのまま残りました。


組み込み演算子@shin を使用して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>

おすすめ記事