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コードを含めることはできません。
このソリューションはエレガントではありませんが、機能します。 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
この質問は別のスレッドで質問されており、これが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
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';
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"
_を取り出すことができます。
上記の回答の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
コマンドラインで指定されたファイルに置き換えられます。改善できると確信していますが、これは今のところうまくいきます。
彼らのアイデアに対する以前の両方の回答に感謝します!
このソリューションを使用すると、出力ファイルで同じフォーマットを維持できます
次の行をコピーしてスクリプトに貼り付けます
cat $1 | while read line
do
eval $line
echo $line
eval echo $line
done | uniq | grep -v '\$'
これにより、引数として渡されたファイルが1行ずつ読み取られ、各行を2回出力するように処理されます。1回は置換なし-1回は変数置換あり。次に、重複する行を削除してから、表示されている変数($)を含む行を削除します。
翻訳する変数がわかっていて数が限られている場合は、いつでも自分で翻訳を行うことができます。
sed "s/\$LOG_FILE_PATH/$LOG_FILE_PATH/g" input > output
また、変数自体がすでにわかっていると仮定します
次の内容の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
....
はいevalは慎重に使用する必要がありますが、問題に対してこの単純なワンライナーを提供してくれました。以下は、ファイル名を使用した例です。
eval "echo \"$(<Text_File.msh)\""
私は自分の目的のためにechoの代わりにprintfを使用しますが、それでうまくいくはずです。私の問題を解決するリンクを提供してくれてありがとうabyss.7。それが役に立てば幸い。