jqを使って複数のフィールド値を見つけて置き換える方法は?

jqを使って複数のフィールド値を見つけて置き換える方法は?

次のjsonファイルから

{
  "email": "xxx",
  "pass": "yyy",
  "contact": [
    {
      "id": 111,
      "name": "AAA"
    }
  ],
  "lname": "YYY",
  "name": "AAA",
   "group": [
    {
      "name": "AAA",
      "lname": "YYY",
    }
  ],

「name」キーを見つけて、その値を「XXX」に置き換える必要があります。どのjqコマンドがこれを実行しますか?

ベストアンサー1

jqの割り当てタスクは、複数の場所で同時に更新を実行でき、この状況のた​​めに設計されています。あなたはそれを使用することができます

jq '(.. | .name?) |= "XXXX"'

到着どこでも「名前」という名前のすべてのフィールドを見つけ、各フィールドの値を一度に置き換えます。「XXXX」で結果オブジェクトを出力します。

これはただ..|.a?出てきた再帰下降文書結合するジョブの更新

それを使う再帰下降演算子..ツリー内の各値を見つけ、各値から「名前」フィールドを抽出します。そして.name一致しない値に対するエラーを抑制します。?その後、「XXXX」を使用して、これらすべての場所のオブジェクトを一度に更新します。代入演算子の更新|=、新しいオブジェクトを出力します。

これはファイル構造に関係なく機能し、すべての場所のすべての名前フィールドを更新します。


または、ファイルには常にこの構造があります。変更したい特定の「名前」フィールド、以前の名前だけでなく、名前を一覧表示してグループに割り当てることもできます。

jq '(.name, .contact[].name, .group[].name) |= "XXXX"'

これは同じ割り当てを実行します。

  1. 最上位オブジェクトの「名前」フィールドです。
  2. 「名前」フィールドすべて連絡先配列のオブジェクト
  3. 「グループ」配列内の各オブジェクトの「名前」フィールド。

一度に完了します。これは、ファイルに次のものがある場合に特に便利です。その他名前フィールドが無関係な場所にあり、変更したくありません。指定された3つのセットの位置のみを探して同時に更新します。


値がここと同じリテラルの場合簡単な割り当てと=また、動作し、キャラクターを保存します。(..|.name?)="XXXX"- 最上位オブジェクト全体に基づいて値を計算する場合でも、この機能が必要です。古い名前に基づいて新しい名前を計算するには:必要|=何を使用するのかわからない場合は、一般的に極端なケースでより良い動作を|=示します。

お持ちの場合複数の交換が必要、一緒に接続することができます。

jq '(..|.name?) = "XXXX" | (..|.lname?) = "1234"'

「name」フィールドと「lname」フィールドはどこでも更新され、更新されたオブジェクト全体が一度出力されます。


効果があるかもしれない他のアプローチ:

  • 何を選択するかを非常に具体的に指定することもできます。

      (..|objects|select(has("name"))).name |= "XXXX"`
    

すべてを検索し、オブジェクトのみを検索し、「名前」を持つオブジェクトのみを検索し、そのオブジェクトの名前フィールドを探し、以前と同じ更新を実行します。

  • jqの開発バージョンを実行している場合(可能性なし)walk機能次の操作も実行されますwalk(.name?="XXXX")。他のすべてのバージョンは、最新リリースバージョン1.5で実行されます。

  • 複数の更新の別のタイプは次のとおりです。

      jq '(..|select(has("name"))?) += {name: "XXXX", lname: "1234"}'
    

それはすべてを見つけるそして名前を指定し、各オブジェクトに「name」と「lname」を設定します。算術更新の割り当て*=そして+オブジェクトのマージ動作

おすすめ記事