104

bash(強制?)を文字列(ファイルからロードされた)に変数を展開させる方法を考え出そうとしています。

「something.txt」という内容のファイルがあります。

hello $FOO world

それから私は走ります

export FOO=42
echo $(cat something.txt)

これは次を返します:

   hello $FOO world

変数が設定されていても、$FOO は展開されませんでした。ファイルを評価またはソースすることはできません-実行しようとするためです(そのままでは実行できません-変数が補間された文字列が必要です)。

何か案は?

4

13 に答える 13

129

私は、この質問に対する答えだと思うもの、つまり envsubstコマンドに出くわしました。

envsubst < something.txt

例: ファイル source.txt 内の変数を置換し、それをさらに処理するために destination.txt に書き込むには

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

ディストリビューションでまだ利用できない場合は、GNU パッケージにありますgettext

@ロッカライト

  • 「$」の問題を処理するために、小さなラッパー スクリプトを作成しました。

(ところで、入力内の変数の一部のみを展開するためにhttps://unix.stackexchange.com/a/294400/7088で説明されている envsubst の「機能」があり ますが、例外をエスケープすることははるかに重要であることに同意します便利。)

これが私のスクリプトです:

#! /bin/bash
      ## -*-Shell-Script-*-
CmdName=${0##*/}
Usage="usage: $CmdName runs envsubst, but allows '\$' to  keep variables from
    being expanded.
  With option   -sl   '\$' keeps the back-slash.
  Default is to replace  '\$' with '$'
"

if [[ $1 = -h ]]  ;then echo -e >&2  "$Usage" ; exit 1 ;fi
if [[ $1 = -sl ]] ;then  sl='\'  ; shift ;fi

sed 's/\\\$/\${EnVsUbDolR}/g' |  EnVsUbDolR=$sl\$  envsubst  "$@"
于 2015-08-10T18:13:41.730 に答える
26

あなたが試すことができます

echo $(eval echo $(cat something.txt))
于 2012-05-21T11:14:21.957 に答える
8

各行を出力するのではなく、Bash が変数置換を実行できるように評価する必要があります。

FOO=42
while read; do
    eval echo "$REPLY"
done < something.txt

詳細についてはhelp eval、または Bash のマニュアルを参照してください。

于 2012-05-21T10:23:10.967 に答える
7

別のアプローチ(厄介なようですが、とにかくここに入れています):

something.txt の内容を一時ファイルに書き込み、echo ステートメントで囲みます。

something=$(cat something.txt)

echo "echo \"" > temp.out
echo "$something" >> temp.out
echo "\"" >> temp.out

次に、それを変数に戻します。

RESULT=$(source temp.out)

$RESULT はすべて展開されます。しかし、それは間違っているようです!


一時ファイルを必要としない単一行のソリューション:

RESULT=$(source <(echo "echo \"$(cat something.txt)\""))
#or
RESULT=$(source <(echo "echo \"$(<something.txt)\""))
于 2012-05-22T02:27:50.870 に答える
4

変数参照のみを展開したい場合(私が自分で持っていた目的)、以下を実行できます。

contents="$(cat something.txt)"
echo $(eval echo \"$contents\")

(ここでは、$contents を囲むエスケープされた引用符が重要です)

于 2015-08-13T20:25:11.003 に答える