2016-04-12 6 views
4

特定の条件で更新する必要があるjsonファイルがあります。ファイル上で直接テキストを置き換えるJq(sed -iなど)

サンプルJSON

{ 
    "Actions" : [ 
     { 
     "value" : "1", 
     "properties" : { 
      "name" : "abc", 
      "age" : "2", 
      "other ": "test1" 
      } 
     }, 
     { 
     "value" : "2", 
     "properties" : { 
      "name" : "def", 
      "age" : "3", 
      "other" : "test2" 
      } 
     } 
    ] 
} 

(端末に出力)出力

{ 
    "value": "1", 
    "properties": { 
    "name": "abc", 
    "age": "2", 
    "other ": "test1" 
    } 
} 
{ 
    "value": "2", 
    "properties": { 
    "name": "def", 
    "age": "3", 
    "other": "no-test" 
    } 
} 

cat sample.json | jq '.Actions[] | select (.properties.age == "3") .properties.other = "no-test"' 

以下のように私は、JQの使用が値と更新に一致するようになり、スクリプトを書いています

このコマンドは必要な変更を行いますが、端末上のjson全体を出力し、cファイルそのものに接続します。

jqがファイルに直接変更を加えるオプションがあるかどうかを教えてください(sed -iに似ています)。

答えて

3

コンテキストを変更せずにアクションオブジェクトを更新したいと思うでしょう。そこにパイプを置くことで、コンテキストを個々のアクションに変更します。かっこで制御できます。

$ jq --arg age "3" \ 
'(.Actions[] | select(.properties.age == $age).properties.other) = "no-test"' sample.json 

これは得られるはず:

{ 
    "Actions": [ 
    { 
     "value": "1", 
     "properties": { 
     "name": "abc", 
     "age": "2", 
     "other ": "test1" 
     } 
    }, 
    { 
     "value": "2", 
     "properties": { 
     "name": "def", 
     "age": "3", 
     "other": "no-test" 
     } 
    } 
    ] 
} 

あなたが入力ファイルを置き換えるために結果をファイルにリダイレクトすることができます。 sedのように、ファイルへのインプレース更新は行いません。

+0

おかげでジェフとファイルへのパイプバックspongeにそれで、これは超便利です。条件付きjsonの変更を直接ファイルに適用するにはどのようなツールをお勧めしますか?私はたくさんのファイルを持っていて、それぞれ別のファイルに書き込むのは簡単ではないでしょう。再度、感謝します。 – Supra

+0

コマンドラインで実行する必要がある場合は、jqが最適です。あなたはそれでかなり多くをすることができます。より多くの制御を必要とする複雑な更新が必要な場合は、お気に入りのスクリプト/プログラミング言語を使用して更新を行うスクリプトを作成するだけです。 –

4

この投稿はのsedの「-i」オプションと同等の有無についての質問に対処し、特に状況が説明:

私は、ファイルの束を持っているし、別のファイルにそれぞれ1を書きます容易ではないでしょう。

少なくともMacやLinuxなどの環境で作業する場合は、いくつかのオプションがあります。

一つはのラインに沿って「& &」を使用することです:彼らの長所と短所が http://backreference.org/2011/01/29/in-place-editing-of-files/ で議論されているので、私はちょうど3つのテクニックに焦点を当てます

jq ... INPUT > INPUT.tmp && mv INPUT.tmp INPUT 

別のを使用することですspongeユーティリティ(GNUの一部moreutils):避けることが有利である場合に第三のオプションは有用かもしれない

jq ... INPUT | sponge INPUT 

変更がなければファイルを更新します。ここでは、このような機能を説明するスクリプトは次のとおりです。

#!/bin/bash 

function maybeupdate { 
    local f="$1" 
    cmp -s "$f" "$f.tmp" 
    if [ $? = 0 ] ; then 
     /bin/rm $f.tmp 
    else 
     /bin/mv "$f.tmp" "$f" 
    fi 
} 

for f 
do 
    jq . "$f" > "$f.tmp" 
    maybeupdate "$f" 
done 
0

Using my answer to a duplicate question

割り当てが変更したアクション配列

.Actionsに新しい値を割り当てることができるように実行割り当てとオブジェクト全体を印刷します
.Actions=([.Actions[] | if .properties.age == "3" then .properties.other = "no-test" else . end]) 

if文を使用しましたが、同じコードを使用して同じことを行うことができます

.Actions=[.Actions[] | select (.properties.age == "3").properties.other = "no-test"] 

上記は、編集された.Actionsでjson全体を出力します。 JQは、機能のようなsed -iを持っていませんが、あなたがする必要があるすべては| sponge

jq '.Actions=([.Actions[] | if .properties.age == "3" then .properties.other = "no-test" else . end])' sample.json | sponge sample.json 
+0

'CMD < FILE > FILE 'または同等の行に沿った入力への配管出力は、一般的に厳しく非難されています(例:http://stackoverflow.com/questions/3055005/bash-is-it-ok-to-use-same)。 -put-of-a-piped-commandとしての入力ファイル多くの良い選択肢がありますので、それに応じて応答を調整してください。 – peak

+0

youre right @peak、私はスポンジを使用するように変更しました –

関連する問題