1. 概要

テンプレートを使用して、同じパターンまたはルールに従うドキュメントを作成することがよくあります。 たとえば、Webテンプレートの動的な部分を埋めて、さまざまなWebページを生成します。

通常、テンプレートはいくつかの変数を持つテキストファイルです。 テンプレートから具体的なドキュメントを作成する場合は、テンプレート内の変数を実際の値に置き換えます。

このチュートリアルでは、Linuxコマンドラインのテキストファイルでシェル変数をそれらの値に置き換える方法を学習します。

2. 問題の紹介

いつものように、例を通して問題を説明しましょう。

まず、テンプレートファイルを見てみましょう。

$ cat template.txt 
Hey $USER,
Nice to see you on this server!
Your home directory is: $HOME

template.txtファイルはプレーンテキストファイルです。 サーバー上のログインユーザーへのメッセージです。

上記のファイルコンテンツでわかるように、テンプレートにはメッセージを動的にするためのシェル変数が含まれています。 したがって、具体的なメッセージを生成するには、テンプレートファイルのシェル変数を実際の値に置き換える必要があります。

次に、テンプレートからメッセージを生成する方法を見てみましょう。

このチュートリアルの後半では、現在のテンプレートファイルを拡張して新しい要件をカバーします。

3. evalは正しい方法ではありません

evalコマンドは引数を連結することでコマンドを作成できることがわかっています

したがって、この問題を解決するには、テンプレートファイルから各行を読み取り、コマンド eval echo“ $ line”を作成することをお勧めします。 「$line 」にシェル変数が含まれている場合、evalはそれらを値として評価します。

3.1. evalを使用したコマンドの作成

それでは、アイデアを実装して、テンプレートファイルから期待されるメッセージを作成できるかどうかをテストしてみましょう。

$ rm -f message.txt; while read line
do  
    eval echo "$line" >> message.txt
done < "template.txt" 

$ cat message.txt
Hey kent,
Nice to see you on this server!
Your home directory is: /home/kent

evalコマンドをwhileループに入れて、各行をmessage.txtという出力ファイルに追加するコマンドを作成しました。

実行後、 cat の出力が示すように、message.txtファイルには期待されるコンテンツが含まれています。 さらに、すべてのシェル変数がそれらの値に置き換えられました。

3.2. いくつかの問題

問題の解決策を見つけたようです。

ただし、評価アプローチにはいくつかの問題がある可能性があります。 template.txtファイルにさらに2行追加しましょう。

$ cat template.txt 
...
# If you like using Java, the Java home is: $JAVA_HOME
Also, you can use command substitution: $(YOUR_CMD)

それでは、コマンドを再実行して、どのメッセージが作成されるかを見てみましょう。

$ rm -f message.txt; while read line
do
    eval echo "$line" >> message.txt
done < "template.txt" 
zsh: command not found: YOUR_CMD

ご覧のとおり、コマンドを実行するとエラーメッセージが表示されます。 これは、テンプレートに $(YOUR_CMD)を追加したためです。 これは変数ではないため、作成されたmessage.txtファイルでは変更されないことが予想されます。 ただし、evalは連結されたセグメントを評価します。 つまり、コマンド置換として $(YOUR_CMD)を実際に実行します。 ただし、もちろん、YOUR_CMDコマンドは使用できません。

この例では無効なコマンドを追加し、エラーメッセージが表示されました。 エラーがシステムに害を及ぼさないので、私たちは幸運です。 ただし、「 rm *」– などの有効なコマンドを追加した場合、予期しない結果または望ましくない結果が生じる可能性があることを想像してみてください。 したがって、この問題を解決するためにevalを使用することは危険である可能性があります

次に、コマンドの実行にエラーがありますが、生成されたmessage.txtを見てみましょう。

$ cat message.txt 
Hey kent,
Nice to see you on this server!
Your home directory is: /home/kent

Also, you can use command substitution:

上記の出力が示すように、私たちが話していたエラーのために、最後の行が切り捨てられました。

それとは別に、「」で始まる行が空白行になっていることがわかります。 これは、評価中に evalが「#」で始まる行をコメントとして扱い、それらを空として評価するためです。

したがって、evalはこの問題を解決するための適切なツールではありません。

4. envsubstコマンドの使用

evalがこの問題に使用するのに適切なツールではない理由を学びました。 それでは、envsubstコマンドを紹介しましょう。

envsubst ユーティリティは、 gettext パッケージのメンバーであり、ほとんどの最新のLinuxディストリビューションにデフォルトでプリインストールされています。

envsubstは、シェル形式の文字列で環境変数を置き換えることができます。 その構文は非常に単純です。

envsubst <TEMPLATE_FILE

上記のコマンドは、出力をStdoutに出力します。 必要に応じて、出力をファイルにリダイレクトできます。

envsubst <TEMPLATE_FILE >OUTPUT_FILE

簡単にするために、このチュートリアルでは出力をStdoutに出力します。

4.1. 環境変数の置換

次に、テンプレートファイルで envsubst コマンドをテストして、期待どおりの結果が得られるかどうかを確認しましょう。

$ envsubst <template.txt 
Hey kent,
Nice to see you on this server!
Your home directory is: /home/kent
# If you like using Java, the Java home is: /usr/lib/jvm/default
Also, you can use command substitution: $(YOUR_CMD)

素晴らしい、それは仕事をします! 上記の出力でわかるように、すべての変数はそれらの値に置き換えられています。

envsubstは、セキュリティ上の理由から、$ {variable-default}、$(command-list)、`command-list`などのシェルによって行われた置換を無視することに注意してください。

4.2. シェルスクリプトでの非環境変数の置換

テンプレートファイルを確認すると、これまでのところ、 $USER$HOMEなどの環境変数のみが含まれていることがわかります。

実際には、テンプレートに非環境変数を含めることができます。 テンプレートファイルにもう1行追加しましょう。

$ cat template.txt
Hey $USER,
...
Also, you can use command substitution: $(YOUR_CMD)
If you have any problem, please contact our admin: <$ADMIN1> or <$ADMIN2>.

ご覧のとおり、テンプレートに $ADMIN1$ADMIN2の2つの新しい変数が導入されました。 それらは環境変数ではありません。

さらに、現実の世界では、テンプレートからメッセージを自動的に生成するスクリプトを作成する可能性があります。

次に、簡単なスクリプトを作成して、2つの「ADMIN」変数を宣言しましょう。

$ cat gen.sh
#!/bin/bash
[email protected]
[email protected]

envsubst <template.txt

次に、スクリプトをテストしてみましょう。

$ ./gen.sh 
Hey kent,
Nice to see you on this server!
Your home directory is: /home/kent
# If you like using Java, the Java home is: /usr/lib/jvm/default
Also, you can use command substitution: $(YOUR_CMD)
If you have any problem, please contact our admin: <> or <>.

ご覧のとおり、すべての環境変数がそれらの値に置き換えられています。 ただし、2つの「ADMIN」変数は空です。

これは、envsubstが環境変数でのみ機能するためです。

この問題の修正は、2つの変数を export して、そのシェルから作成されたすべての子プロセスで使用できるようにすることです。

$ cat gen.sh
#!/bin/bash
export [email protected]
export [email protected]

envsubst <template.txt

$ ./gen.sh 
Hey kent,
...
If you have any problem, please contact our admin: <[email protected]> or <[email protected]>.

5. 結論

この記事では、例を通じてenvsubstを使用してテンプレート内のシェル変数を置き換える方法を学習しました。

また、evalが問題を解決するための適切なツールではない理由についても説明しました。