jqを使用して配列にJSONオブジェクトを追加する

jqを使用して配列にJSONオブジェクトを追加する

jq私の目標は、bashのコマンド出力を使用してJSONオブジェクトを出力することです。find1行のコマンドでも bash スクリプトでもかまいません。

各出力行にJSONオブジェクトを生成するための次のコマンドがあります。

find ~/ -maxdepth 1 -name "D*" | \
while read line; \
do jq -n \
--arg name "$(basename "$line")" \
--arg path "$line" \
'{name: $name, path: $path}'; \
done

出力は次のとおりです。

{
  "name": "Desktop",
  "path": "/Users/username/Desktop"
}
{
  "name": "Documents",
  "path": "/Users/username/Documents"
}
{
  "name": "Downloads",
  "path": "/Users/username/Downloads"
}

ただし、これらのオブジェクトが配列に存在し、その配列がitems次のように親オブジェクトの単一キー値になるようにする必要があります。

{"items": [
    {
      "name": "Desktop",
      "path": "/Users/username/Desktop"
    },
    {
      "name": "Documents",
      "path": "/Users/username/Documents"
    },
    {
      "name": "Downloads",
      "path": "/Users/username/Downloads"
    }
  ]
}

jq各行の出力文字列に角かっこを追加し('[{name: $name, path: $path}]';)、角括弧を追加しましたが、配列要素間にカンマは追加しませんでした。

可能な解決策を見つけましたここしかし、各行を繰り返しながら使用する方法がわかりません。

答え1

このjq 1.5 inputsストリーミングフィルタトリックは効果があるようです。

... | jq -n '.items |= [inputs]'

前任者。

$ find ~/ -maxdepth 1 -name "D*" | 
    while read line; do 
      jq -n --arg name "$(basename "$line")" \
            --arg path "$line" \
        '{name: $name, path: $path}'
    done | jq -n '.items |= [inputs]'
{
  "items": [
    {
      "name": "Downloads",
      "path": "/home/steeldriver/Downloads"
    },
    {
      "name": "Desktop",
      "path": "/home/steeldriver/Desktop"
    },
    {
      "name": "Documents",
      "path": "/home/steeldriver/Documents"
    }
  ]
}

答え2

jq呼び出しから直接find結果データを使用して、jqシェルループなしで最終出力を構築します。

find ~ -maxdepth 1 -name '[[:upper:]]*' \
    -exec jq -n --arg path {} '{ name: ($path|sub(".*/"; "")), path: $path }' \; |
jq -n -s '{ items: inputs }'

見つかったパス名ごとにJSONオブジェクトを作成して実行されますjq-exec値の最後のスラッシュまで、パス名のすべての内容を削除し、nameパス名をそのまま値として使用しますpath

最後に、jqデータをfind配列として読み込み、-s新しいitemsJSONオブジェクトに配列として挿入します。最後のjq呼び出しは次のように書くこともできますjq -n '{ items: [inputs] }

[[:upper:]*結果の例(代替パターンを使用していることに注意してくださいD*):-namefind

{
  "items": [
    {
      "name": "Documents",
      "path": "/home/myself/Documents"
    },
    {
      "name": "Mail",
      "path": "/home/myself/Mail"
    },
    {
      "name": "Work",
      "path": "/home/myself/Work"
    }
  ]
}

答え3

プログラミング言語を使うのが気に入らないのはとても簡単です。以下はPHPの例です:

<?php
$m1 = [
   'items' => []
];
$a1 = glob('~/D*');
foreach ($a1 as $s1) {
   $m1['items'][] = [
      'name' => basename($s1),
      'path' => $s1
   ];
}
echo json_encode($m1, JSON_PRETTY_PRINT);

関連情報