web-dev-qa-db-ja.com

テキストファイルでシェル変数を展開する方法は?

ASCIIテキストファイル(シェル以外のスクリプト言語のコードが含まれているとしましょう)を考えてみましょう:

Text_File.msh:

spool on to '$LOG_FILE_PATH/logfile.log';
login 'username' 'password';
....

これがシェルスクリプトの場合、$ sh Text_File.mshとして実行すると、シェルが変数を自動的に展開します。私がやりたいのは、シェルにこれらの変数を展開させてから、次のようにText_File_expanded.mshとして新しいファイルを作成することです。

Text_File_expanded.msh:

spool on to '/expanded/path/of/the/log/file/../logfile.log';
login 'username' 'password';
....

考えてみましょう:

$ a=123
$ echo "$a"
123

したがって、技術的にはこれでうまくいくはずです。

$ echo "`cat Text_File.msh`" > Text_File_expanded.msh

...しかし、それは期待どおりに機能せず、出力ファイルはソースと同じです。

そのため、これを実現する方法がわかりません。私の目標は、シェル以外のスクリプトに埋め込まれているディレクトリパスを簡単に維持できるようにすることです。 これらのスクリプトはUNIXシェルによってコンパイルされていないため、UNIXコードを含めることはできません。

17
Kent Pawar

このソリューションはエレガントではありませんが、機能します。 Shell_expansion.shを呼び出すスクリプトを作成します。

echo 'cat <<END_OF_TEXT' >  temp.sh
cat "$1"                 >> temp.sh
echo 'END_OF_TEXT'       >> temp.sh
bash temp.sh >> "$2"
rm temp.sh

次に、次のようにこのスクリプトを呼び出すことができます。

bash Shell_expansion.sh Text_File.msh Text_File_expanded.msh
9
Hai Vu

この質問は別のスレッドで質問されており、これがIMOのベストアンサーです。

export LOG_FILE_PATH=/expanded/path/of/the/log/file/../logfile.log
cat Text_File.msh | envsubst > Text_File_expanded.msh

macの場合は、最初にgettextをインストールします:brew install gettext

参照: ファイルからロードされた文字列内の変数をbashに強制的に展開させる

32
Dima Lituiev

Perlソリューションで問題がない場合:

サンプルファイル:

$ cat file.sh
spool on to '$HOME/logfile.log';
login 'username' 'password';

解決:

$ Perl -pe 's/\$(\w+)/$ENV{$1}/g' file.sh
spool on to '/home/user/logfile.log';
login 'username' 'password';
9
Guru

1行で表示したい場合(私はbashの専門家ではないため、注意点があるかもしれませんが、試したすべての場所で機能します):

test.txtに含まれる場合

_${line1}
${line2}
_

その後:

_>line1=fark
>line2=fork
>value=$(eval "echo \"$(cat test.txt)\"")
>echo "$value"
line1 says fark
line2 says fork
_

もちろん、印刷したいだけの場合は、余分なvalue=$()と_echo "$value"_を取り出すことができます。

8

上記の回答の1つの制限は、両方とも変数を環境にエクスポートする必要があることです。これが私が思いついたもので、変数を現在のシェルスクリプトに対してローカルにすることができます。

#!/bin/sh
FOO=bar;
FILE=`mktemp`; # Let the Shell create a temporary file
trap 'rm -f $FILE' 0 1 2 3 15;   # Clean up the temporary file 

(
  echo 'cat <<END_OF_TEXT'
  cat "$@"
  echo 'END_OF_TEXT'
) > $FILE
. $FILE

上記の例では、変数$FOOコマンドラインで指定されたファイルに置き換えられます。改善できると確信していますが、これは今のところうまくいきます。

彼らのアイデアに対する以前の両方の回答に感謝します!

8
Paul Gear

このソリューションを使用すると、出力ファイルで同じフォーマットを維持できます

次の行をコピーしてスクリプトに貼り付けます

cat $1 | while read line
do
  eval $line
  echo $line
  eval echo $line
done | uniq | grep -v '\$'

これにより、引数として渡されたファイルが1行ずつ読み取られ、各行を2回出力するように処理されます。1回は置換なし-1回は変数置換あり。次に、重複する行を削除してから、表示されている変数($)を含む行を削除します。

1
hcii

翻訳する変数がわかっていて数が限られている場合は、いつでも自分で翻訳を行うことができます。

sed "s/\$LOG_FILE_PATH/$LOG_FILE_PATH/g" input > output

また、変数自体がすでにわかっていると仮定します

1
tvCa

次の内容のASCIIファイルtest.txtを作成します。

Try to replace this ${myTestVariable1} 
bla bla
....

次に、変数名を含む「subsed」ファイルを作成します。

's,${myTestVariable1},'"${myTestVariable1}"',g;
s,${myTestVariable2},'"${myTestVariable2}"',g;
s,${myTestVariable3},'"${myTestVariable3}"',g;
s,${myTestVariable4},'"${myTestVariable4}"',g'

ターミナルを開き、test.txtとsub.sedを含むフォルダーに移動します。
置き換える変数の値を定義します

myTestVariable1=SomeNewText

次に、sedを呼び出してその変数を置き換えます

sed "$(eval echo $(cat sub.sed))" test.txt > test2.txt

出力は次のようになります

$cat test2.txt

Try to replace this SomeNewText 
bla bla
....
0
mcExchange

はいevalは慎重に使用する必要がありますが、問題に対してこの単純なワンライナーを提供してくれました。以下は、ファイル名を使用した例です。

eval "echo \"$(<Text_File.msh)\""

私は自分の目的のためにechoの代わりにprintfを使用しますが、それでうまくいくはずです。私の問題を解決するリンクを提供してくれてありがとうabyss.7。それが役に立てば幸い。

0
MarcT