121

シェル変数 ($VAR1 または $VAR2 など) を導入したテキスト ファイルがいくつかあります。

これらのファイルを (1 つずつ) 取得し、すべての変数が置き換えられた新しいファイルに保存したいと思います。

これを行うために、次のシェル スクリプトを使用しました (StackOverflow にあります)。

while read line
do
    eval echo "$line" >> destination.txt
done < "source.txt"

これは非常に基本的なファイルで非常にうまく機能します。

しかし、より複雑なファイルでは、「eval」コマンドはあまりにも多くのことを行います:

  • 「#」で始まる行はスキップされます

  • XML ファイルの解析で大量のエラーが発生する

それを行うより良い方法はありますか?(シェルスクリプトで...たとえば、これはAntで簡単に実行できることを知っています)

敬具

4

12 に答える 12

269

見てみると、私のシステムにはenvsubstgettext-base パッケージの一部であるコマンドがあることがわかりました。

したがって、これにより簡単になります。

envsubst < "source.txt" > "destination.txt"

sponge両方に同じファイルを使用する場合は、Johnny Utahh: が提案するように、 moreutil's のようなものを使用する必要がありますenvsubst < "source.txt" | sponge "source.txt"。(そうしないと、シェル リダイレクトによってファイルが読み取られる前に空になるためです。)

于 2013-01-04T12:54:10.743 に答える
81

回答2を参照して、envsubstについて話し合うときに、次のように尋ねました。

.sh スクリプトで宣言されている変数を使用するにはどうすればよいですか?

答えは、 を呼び出す前に変数をエクスポートするだけですenvsubst

引数を使用して、入力内で置換する変数文字列を制限することもできenvsubst SHELL_FORMATます (入力内の文字列が、一般的なシェル変数値で意図せず置換されることを回避します - 例: $HOME)。

例えば:

export VAR1='somevalue' VAR2='someothervalue'
MYVARS='$VAR1:$VAR2'

envsubst "$MYVARS" <source.txt >destination.txt

$VAR1andのすべてのインスタンス (およびand$VAR2のみ)をそれぞれVAR1andに置き換えます。VAR2source.txt'somevalue''someothervalue'

于 2014-01-21T17:31:18.823 に答える
22

このトピックが古いことは知っていますが、変数をエクスポートしない、より単純な作業ソリューションがあります。ワンライナーにすることもできますが、私は行末を使用\して分割することを好みます。

var1='myVar1'\
var2=2\
var3=${var1}\
envsubst '$var1,$var3' < "source.txt" > "destination.txt"

#         ^^^^^^^^^^^    ^^^^^^^^^^     ^^^^^^^^^^^^^^^
# define which to replace   input            output

envsubst環境変数と見なされるには、変数を同じ行に定義する必要があります。

指定された'$var1,$var3'ものだけを置き換えるオプションです。${VARIABLE_USED_BY_JENKINS}置き換えてはならないものを含む入力ファイルを想像してください。

于 2018-02-13T08:35:24.190 に答える
0

本当にbash(およびsed)のみを使用したい場合は、各環境変数(setposixモードで返される)を調べ-e 'regex'て、そこからsedの束を作成し、で終了してから、-e 's/\$[a-zA-Z_][a-zA-Z0-9_]*//g'すべてをに渡します。 sed。

ただし、Perlの方が優れた仕事をします。配列として環境変数にアクセスでき、実行可能ファイルの置換を実行できるため、環境変数を1回だけ照合できます。

于 2013-01-04T11:03:02.280 に答える
0

実際には、バックスラッシュを無視するように変更readする必要があります。read -r

また、引用符と円記号はエスケープする必要があります。それで

while read -r line; do
  line="${line//\\/\\\\}"
  line="${line//\"/\\\"}"
  line="${line//\`/\\\`}"
  eval echo "\"$line\""
done > destination.txt < source.txt

それでも拡張を行うにはひどい方法です。

于 2013-01-04T11:07:23.160 に答える