

コマンドで設定した変数をファイルの変数に代入したいのですが、代入する方法が分からず困っています。  
ファイルの中の変数に、ファイル外の値を代入する方法はないのでしょうか？  
以下、 `$ bash ./test.sh`を実行し、  
sample.jsonが`"green": "123"`になるような結果を得たいです。

**sample.json**

[code]

    {
        "red": "aaaaa",
        "green": "$ver",
        "yellow": "ccccc",
        "blue": "ddddd"
    }
    
[/code]

**test.sh**

[code]

    #!/bin/bash
    ver="123"
    cat docs/template.json
    
[/code]

ディレクトリ構成↓

├─sample.json  
└─test.sh

echoコマンドでtest.sh内で変数を表示することはできているので、  
試しにcatコマンドを使って変数を出力できないかとtest.shを書き換えて試しましたが、  
そもそも変数を出力することができず、困っています。  
**test.sh**

[code]

    #!/bin/bash
    ver="1234"
    echo $ver
    # cat docs/template.json
    cat << EOS > sample1.json
    $ver
    EOS
    
[/code]

得られたsample1.json

[code]

    
    
[/code]


CC BY-SA 4.0
2020-04-12T13:19:08.103
65565
2020-04-13T04:21:28.103
2020-04-13T04:21:28.103
39601
39601
question
bash shellscript
Bashでファイルの変数に値を代入したい


`envsubst`を使ってみては？環境変数を展開してくれます。

[code]

    cat sample.json | ver=123 envsubst 
    
[/code]

**参考**

  * [低機能でポータブルなテンプレートエンジンが欲しい→そこでenvsubstですよ - Qiita](https://qiita.com/hnw/items/3d8bad7852510c3a84d7)
  * [bashで環境変数をexportせずにシェルスクリプトを実行したい場合はコマンドの前に記述することで代替できる - コード日進月歩](https://shinkufencer.hateblo.jp/entry/2018/10/19/235900)
    * `ver=123`が何をしてるかの説明です。


CC BY-SA 4.0
2020-04-12T14:39:19.637
65567
2020-04-12T14:39:19.637
12561
65565
answer


# 回答

shスクリプトに次のワンライナーを追加して、`cat`の代わりに`extcat`を使用すればご要望の結果が得られます。

shスクリプト版も追記しました。こちらの方が使い勝手はよいです。

### ワンライナー

`function extcat () { cat $@ | bash <<< "cat <<< "\""$(cat)"\""" ; };export -f
extcat`

**注意**  
環境変数の展開だけでなく。「コマンド置換」も行われますので、使用するときは注意が必要です。

よろしければ使ってみてください。

[簡易テンプレートエンジン extcat coneta
#1](https://qiita.com/EjiriAkira/items/30bfb2520744094a3679)

### test.sh

[code]

    #!/bin/bash
    function extcat () { cat $@ | bash <<< "cat <<< "\""$(cat)"\""" ; };export -f extcat
    ver="123" extcat docs/template.json > sample.json
    
[/code]

または

[code]

    #!/bin/bash
    function extcat () { cat $@ | bash <<< "cat <<< "\""$(cat)"\""" ; };export -f extcat
    export ver="123"
    extcat docs/template.json > sample.json
    
[/code]

### sample.json

[code]

    {
        "red": "aaaaa",
        "green": "123",
        "yellow": "ccccc",
        "blue": "ddddd"
    }
    
[/code]

### docs/template.json

テンプレートの先頭に`"'`を、末尾に`'"`を付加し、`$ver`を`'`で囲む必要があります。

[code]

    "'{
        "red": "aaaaa",
        "green": "'$ver'",
        "yellow": "ccccc",
        "blue": "ddddd"
    }'"
    
[/code]

テンプレートの変数置換は`bash`の機能を利用しています。  
テンプレートは二重引用符`”`で囲んでから評価しているため、テンプレートに`”`を使用している場合は引用符を一重引用符`'`に変更し、`${変数名}`の前後で引用を解かなければなりません。

もう一つの方法は、`"`を`\`でエスケープする方法です。

[code]

    {
        \"red\": \"aaaaa\",
        \"green\": \"$ver\",
        \"yellow\": \"ccccc\",
        \"blue\": \"ddddd\"
    }
    
[/code]

### ディレクトリ構成

├─test.sh  
├─docs/template.json  
└─sample.json

* * *

* * *

こちらはextcat のshスクリプト版です。  
テンプレートの二重引用符`"`のエスケープは不要です。

### extcat.sh

[code]

    #!/bin/sh
     cat <<^D | sh
     cat <<^D2
    `cat $@`
    ^D2
    ^D
    
[/code]

`^D`は制御文字のつもりです。コピーペーストして制御文字`＾D`が通常の文字列＾Dになっても動きます。

### 使い方

[code]

    ver="123" ./extcat.sh docs/template.json > sample.json
    
[/code]

### 実行結果(sample.json)

[code]

    {
        "red": "aaaaa",
        "green": "123",
        "yellow": "ccccc",
        "blue": "ddddd"
    }
    
[/code]

### テンプレート(docs/template.json)

[code]

    {
        "red": "aaaaa",
        "green": "$ver",
        "yellow": "ccccc",
        "blue": "ddddd"
    }
    
[/code]


CC BY-SA 4.0
2020-04-12T15:20:13.420
65569
2020-04-13T00:57:19.147
2020-06-17T08:14:45.997
-1
35558
65565
answer


JSON パーサーとして有名な [jq コマンド](https://github.com/stedolan/jq)には質問文にあるような形式の JSON
をテンプレートとみなして処理するオプションがあります: [Using jq as a template
engine](https://github.com/stedolan/jq/wiki/Cookbook#using-jq-as-a-template-
engine)。

[code]

    $ cat sample.json
    {
        "red": "aaaaa",
        "green": $ver,
        "yellow": "ccccc",
        "blue": "ddddd"
    }
    $ cat test.sh
    ver=123
    jq -n --argjson ver "\"$ver\"" -f sample.json > output.json
    $ bash test.sh
    $ cat output.json
    {
      "red": "aaaaa",
      "green": "123",
      "yellow": "ccccc",
      "blue": "ddddd"
    }
    
[/code]

テンプレートの構文が単純なら、sed コマンドで処理する方法もあります。

[code]

    $ cat sample.json
    {
        "red": "aaaaa",
        "green": "$ver",
        "yellow": "ccccc",
        "blue": "ddddd"
    }
    $ cat test.sh
    ver=123
    sed "s/\$ver/$ver/g" sample.json > output.json
    $ bash test.sh
    $ cat output.json
    {
        "red": "aaaaa",
        "green": "123",
        "yellow": "ccccc",
        "blue": "ddddd"
    }
    
[/code]


CC BY-SA 4.0
2020-04-12T15:40:44.673
65570
2020-04-12T15:40:44.673
19110
65565
answer