Как расширить переменные оболочки в текстовом файле?

Рассмотрим текстовый файл ASCII (предположим, что он содержит код языка без оболочки):

Text_File.msh:

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

Теперь, если это была оболочка script, я мог бы запустить ее как $ 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.

Ответ 1

Это решение не изящно, но оно работает. Создайте вызов script 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

Затем вы можете вызвать этот script следующим образом:

bash shell_expansion.sh Text_File.msh Text_File_expanded.msh

Ответ 3

Если решение 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';

Ответ 4

Одно из указанных выше ответов заключается в том, что они оба требуют, чтобы переменные экспортировались в среду. Вот что я придумал, чтобы переменные были локальными для текущей оболочки script:

#!/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 "[email protected]"
  echo 'END_OF_TEXT'
) > $FILE
. $FILE

Приведенный выше пример позволяет заменить переменную $FOO в файлах, указанных в командной строке. Я уверен, что его можно улучшить, но это работает для меня до сих пор.

Благодаря предыдущим ответам на их идеи!

Ответ 5

Если вы хотите его в одной строке (я не эксперт 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".

Ответ 6

Если переменные, которые вы хотите перевести, известны и ограничены по количеству, вы всегда можете сделать перевод самостоятельно:

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

И также предполагая, что сама переменная уже известна

Ответ 7

Создайте файл ascii файла test.txt со следующим содержимым:

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

Теперь создайте файл "sub.sed", содержащий имена переменных, например

'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
....

Ответ 8

Это решение позволяет сохранить одно и то же форматирование в файле ouput

Скопируйте и вставьте следующие строки в script

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

это будет читать файл, переданный как аргумент, за строкой, а затем обрабатывать, чтобы попытаться напечатать каждую строку дважды: - один раз без замены - один раз с заменой переменных. затем удалите повторяющиеся строки затем удалите строки, содержащие видимые переменные ($)