JSONで値を確認し、jqを使用して他のキーを変更するには?

JSONで値を確認し、jqを使用して他のキーを変更するには?
[
    {
        "name": "user1",
        "status": "off"
    },
    {
        "name": "user2",
        "status": "off"
    },
    {
        "name": "user3",
        "status": "on"
    }
]

statusたとえば、JSONファイルから値を再帰的に取得し、状態のあるすべての値を取得offする方法を知りたいと思います。nameoff

user1また、合計user2値をどのように変更しますかon

私はとjqを使用していますbash

ベストアンサー1

配列のすべての要素に式を適用して変更された配列を取得するには、を使用しますmap(expression)

状態のあるすべての項目を抽出しますoff

$ jq 'map(select(.status == "off"))' file
[
  {
    "name": "user1",
    "status": "off"
  },
  {
    "name": "user2",
    "status": "off"
  }
]

マッピングは、select(.status == "off")次の要素のみを抽出(選択)して配列を変更します.status == "off"本物

上記でデコードされた名前のみを抽出します。

$ jq -r 'map(select(.status == "off"))[].name' file
user1
user2

前の式の終わりに追加すると、[].name最初に配列を個々の項目のセットに展開し(それがまさにその[]操作です)、.name各項目から値を抽出します。

また、使用することができます

jq -r 'map(select(.status == "off").name)[]' file

...名前配列を作成し、その配列からすべての要素を抽出します。

on状態があるすべての項目の状態を次に設定しますoff

$ jq 'map(select(.status == "off").status = "on")' file
[
  {
    "name": "user1",
    "status": "on"
  },
  {
    "name": "user2",
    "status": "on"
  },
  {
    "name": "user3",
    "status": "on"
  }
]

マッピングを使用すると、状態を持つ要素の状態select(.status == "off").status = "on"をに設定して配列を変更します。onoff

on明示的な名前ベースのエントリの状態を次に設定します。

$ jq 'map(select(.name == "user1" or .name == "user2").status = "on")' file
[
  {
    "name": "user1",
    "status": "on"
  },
  {
    "name": "user2",
    "status": "on"
  },
  {
    "name": "user3",
    "status": "on"
  }
]

同じですが、式に名前をハードコードしないでください。代わりに、コマンドラインの最後にリストとして提供してください(--args名前のリストは〜しなければならないコマンドラインの最後のエントリです):

$ jq 'map(select(IN(.name; $ARGS.positional[])).status = "on")' file --args user1 user2
[
  {
    "name": "user1",
    "status": "on"
  },
  {
    "name": "user2",
    "status": "on"
  },
  {
    "name": "user3",
    "status": "on"
  }
]

指定された名前のリストは、名前付き--args配列にあります$ARGS.positional

状況がIN(a; b)戻ってきました。本物aセットにいる場合b$ARGS.positional[]コマンドラインで指定された名前のセットである検索セットとして使用します。つまり、select()ここではコマンドラインリストに名前が表示される要素のみを抽出し、これらの要素の状態はに設定されますon

IN(a; b)同様の名前の項目とは異なり、次in(a)を返します。本物与えられた値がオブジェクトまたは配列のキーまたはインデックスとして表示される場合a

環境みんな項目の状態は次のとおりですon

$ jq 'map(.status = "on")' file
[
  {
    "name": "user1",
    "status": "on"
  },
  {
    "name": "user2",
    "status": "on"
  },
  {
    "name": "user3",
    "status": "on"
  }
]

コメントの次の質問:

このようにマッチングしたい場合はNOT IN(a, b)どうすればよいですか?明らかに私が尋ねるのは、このような値を渡すと、それ以外のすべてがuser1オフになるということですuser1。どうすればいいですか?

以下は、明示的なステートメントを使用して、if特定の名前の状態を次のように変更します。onoff

jq '
    map(
        if IN(.name; $ARGS.positional[]) then
            .status = "on"
        else
            .status = "off"
        end
    )' file --args user1

または、単一行レイアウトでは、次のことを行います。

jq 'map(if IN(.name; $ARGS.positional[]) then .status = "on" else .status = "off" end)' file --args user1

フォローアップを次のように解釈すると、いいえ状態に関係なく、特定の名前の状態を変更したいのですが、他のすべての状態はに変更したいと思いますoff。この場合、以前のバリエーションで使用されていた条件を無効にすることができます。

jq 'map(select(IN(.name; $ARGS.positional[]) | not).status = "off")' file --args user1

| not後で追加された内容を参照してくださいIN(...; ...)

もちろん、if上記のほとんどのバリエーションでステートメントを使用することもできますが、select()可能であればそれを使用するのが好きです。

おすすめ記事