Как расширить переменные оболочки в текстовом файле?
Рассмотрим текстовый файл 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
Ответ 2
Этот вопрос задан в другом потоке, и это лучший ответ 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 расширять переменные в строке, загруженной из файла
Ответ 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 '\$'
это будет читать файл, переданный как аргумент, за строкой, а затем обрабатывать, чтобы попытаться напечатать каждую строку дважды:
- один раз без замены
- один раз с заменой переменных.
затем удалите повторяющиеся строки
затем удалите строки, содержащие видимые переменные ($)