2017-01-06 3 views
2

Linuxのコマンドラインを使用してJSONファイルを変更したいとします。jqを使用してJSONを変更する

私はこれらの手順を試してみました:

[[email protected]]# INPUT="dsa" 
[[email protected]]# echo $INPUT 
dsa 
[[email protected]]# CONF_FILE=test.json 
[[email protected]]# echo $CONF_FILE 
test.json 
[[email protected]]# cat $CONF_FILE 
{ 
    "global" : { 
    "name" : "asd", 
    "id" : 1 
    } 
} 
[[email protected]]# jq -r '.global.name |= '""$INPUT"" $CONF_FILE > tmp.$$.json && mv tmp.$$.json $CONF_FILE 
jq: error: dsa/0 is not defined at <top-level>, line 1: 
.global.name |= dsa 
jq: 1 compile error 

所望の出力:

jqを使用して
[[email protected]]# cat $CONF_FILE 
    { "global" : { 
    "name" : "dsa", 
    "id" : 1 } } 
+3

ちょっとしたヒント、仕事をするためにrootとしてログインしないでください。 – Kent

答えて

4

唯一の問題は、jqに渡されたスクリプトが誤って引用されたことでした。

一般
jq -r ".global.name = \"$INPUT\"" "$CONF_FILE" > tmp.$$.json && mv tmp.$$.json "$CONF_FILE" 

が、しかし、chepner's helpful answerは、シェル変数を埋め込むより堅牢な代替案を示しています。組み込み\でエスケープ"インスタンスを持つ単一の二重引用符で囲まれた文字列を使用して、特定のケースで

は、おそらく最も簡単ですで直接参照:--argオプションを使用すると、値jqとしてを渡すと、シングルクォーンgスクリプトを使用することをお勧めします。これは、シェルによってどの要素が展開されているかについての混乱を避け、jqに渡される$インスタンスをエスケープする必要性を排除するためです。また

  • だけ=値を代入するのに十分です。 LHSを参照する式ではなくリテラルであるため、この場合は|=(いわゆる更新演算子)も動作しますが、この場合は=と同じように動作します。the manualを参照してください。
  • シェル変数参照を日常的に二重引用符で囲む必要があります。avoid conflicts with environment variables and special shell variablesには大文字の変数名を使用しないでください。 用として

なぜあなたの引用符を動作しませんでした:

  • 文字列リテラル.global.name |=(起因する単一引用符に)
  • '.global.name |= '""$INPUT""は、次のトークンで構成されています

  • 文字列リテラル"" - ie、空の文字列 - jqスクリプト
  • (単語分割とグロブにその値被写体を行う)変数$INPUTから引用符なし参照を見る前に、引用符がなり、シェルによってを除去します。
  • リテラル""の別のインスタンス。 関数名としてdsaを解釈するjqを引き起こし、あなたが見ることができるように

    .global.name |= dsa 
    

    は、二重引用符が欠落している:あなたのサンプル値で

jqは、そのスクリプトとして次の文字列を見終わりましたは文字列リテラルではなく、(存在しない)関数dsaに引数が渡されていないため、jqのエラーメッセージは、dsa/0 - (0)引数のない関数として参照されています。

1

をストレートフォワードフィルタと、あなたのためにそれを行う必要があります。

.global.name = "dsa" 

すなわち

jq '.global.name = "dsa"' json-file 
{ 
    "global": { 
    "name": "dsa", 
    "id": 1 
    } 
} 

あなたはJSON-フィルタ、hereで遊ぶことができます。

+1

'| ='は問題ではありませんでした。引用していた。 – chepner

+0

@chepner:以前にキャッチしていませんでした。 – Inian

+1

また、_filter_は 'jq'の非常に広い概念です([manual](https://stedolan.github.io/jq/manual/)から引用してください: 'jqプログラムは"フィルタ "です:それは入力を受け取り、出力を生成します。 ')、ここで関心のある機能は_assignment_です。 – mklement0

4

それは--argオプションを使用して値を渡すためにはるかに簡単かつ安全です:

jq -r --arg newname "$INPUT" '.global.name |= $newname' "$CONF_FILE" 

これは$INPUTの正確な値を使用してJSON値として引用されていることを保証します。

関連する問題