У меня есть несколько текстовых файлов, в которых я ввел переменные оболочки (например, $ VAR1 или $ VAR2).
Я хотел бы взять эти файлы (один за другим) и сохранить их в новых файлах, где все переменные были бы заменены.
Для этого я использовал следующий сценарий оболочки (можно найти на StackOverflow):
while read line
do
eval echo "$line" >> destination.txt
done < "source.txt"
Это очень хорошо работает с очень простыми файлами.
Но для более сложных файлов команда eval делает слишком много:
Строки, начинающиеся с "#", пропускаются
Анализ XML-файлов приводит к множеству ошибок
Есть ли способ лучше? (в сценарии оболочки ... я знаю, что это легко сделать, например, с помощью Ant)
С уважением
envsubst
является частью GNU gettextsource.txt
содержит какие-либо$
символы вне раскрытия переменной,envsubst
они также будут заменены, и нет возможности избежать$
. Обычный (уродливый) обходной путь -export DOLLAR="$"
.Что касается ответа 2, при обсуждении envsubst вы спросили:
Ответ: вам просто нужно экспортировать свои переменные перед вызовом
envsubst
.Вы также можете ограничить переменные строки, которые вы хотите заменить во входных данных, используя
envsubst
SHELL_FORMAT
аргумент (избегая непреднамеренной замены строки во входных данных общим значением переменной оболочки - например$HOME
).Например:
export VAR1='somevalue' VAR2='someothervalue' MYVARS='$VAR1:$VAR2' envsubst "$MYVARS" <source.txt >destination.txt
Заменим все экземпляры
$VAR1
и$VAR2
(и толькоVAR1
иVAR2
) вsource.txt
с'somevalue'
и'someothervalue'
соответственно.источник
'
, которые используются для установки,MYVARS
имеют решающее значениеexport
,envsubst
или любая команда чередования может завершиться ошибкой, если текст для замены большой. Справка.SHELL_FORMAT
аргумента (т.е."$MYVARS"
) приводит к замене всех экспортируемых переменных. Если это то, что вам нужно, не беспокойтесь.Я знаю, что эта тема старая, но у меня есть более простое рабочее решение без экспорта переменных. Может быть одинарным, но я предпочитаю разделять
\
в конце строки.var1='myVar1'\ var2=2\ var3=${var1}\ envsubst '$var1,$var3' < "source.txt" > "destination.txt" # ^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^ # define which to replace input output
Переменные должны быть определены в той же строке, что и
envsubst
переменные среды.'$var1,$var3'
Не является обязательным только заменить указанные оговорки. Представьте себе входной файл,${VARIABLE_USED_BY_JENKINS}
который не следует заменять.источник
$ export MY_ENV_VAR=congratulation
$MY_ENV_VAR
Вы также можете использовать все другие переменные ENV, определенные вашей системой, например (в linux) $ TERM, $ SHELL, $ HOME ...
$ envsubst "`printf '${%s} ' $(sh -c "env|cut -d'=' -f1")`" < in.txt > out.txt
и вы должны увидеть «поздравление».
источник
Если вы действительно хотите использовать только bash (и sed), я бы прошел через каждую из ваших переменных среды (как возвращено
set
в режиме posix) и построил кучу-e 'regex'
для sed из этого, завершившегося a-e 's/\$[a-zA-Z_][a-zA-Z0-9_]*//g'
, а затем передал все это в sed.Однако Perl справился бы лучше, у вас есть доступ к переменным среды в виде массива, и вы можете выполнять замену исполняемых файлов, чтобы сопоставить любую переменную среды только один раз.
источник
perl -pi -e 'foreach $key(sort keys %ENV){ s/\$$key/$ENV{$key}/g}' "$main_tf_file"
На самом деле вам нужно изменить ваш
read
наread -r
который заставит его проигнорировать обратные косую черту.Кроме того, вам следует избегать кавычек и обратных косых черт. Так
while read -r line; do line="${line//\\/\\\\}" line="${line//\"/\\\"}" line="${line//\`/\\\`}" eval echo "\"$line\"" done > destination.txt < source.txt
Тем не менее, это все еще ужасный способ расширения.
источник
Экспортируйте все необходимые переменные, а затем используйте perl onliner
TEXT=$(echo "$TEXT"|perl -wpne 's#\${?(\w+)}?# $ENV{$1} // $& #ge;')
Это заменит все переменные ENV, присутствующие в TEXT, на фактические значения. Цитаты тоже сохранились :)
источник
Если вы хотите, чтобы переменные env были заменены в ваших исходных файлах, сохраняя при этом все переменные, отличные от env, такими, какие они есть, вы можете использовать следующую команду:
envsubst "$(printf '${%s} ' $(env | sed 's/=.*//'))" < source.txt > destination.txt
Здесь объясняется синтаксис для замены только определенных переменных . Приведенная выше команда использует вспомогательную оболочку для перечисления всех определенных переменных и затем передает ее в
envsubst
Итак, если есть определенная переменная env
$NAME
, и вашsource.txt
файл выглядит так:Hello $NAME Your balance is 123 ($USD)
destination.txt
Будет:Hello Arik Your balance is 123 ($USD)
Обратите внимание, что
$NAME
заменяется, а$USD
остается нетронутымисточник
Вызовите двоичный файл perl в режиме поиска и замены для каждой строки (
-pi
), запустив код perl (-e
) в одинарных кавычках, который выполняет итерацию по ключам специального%ENV
хэша, содержащего имена экспортируемых переменных в качестве ключей и значения экспортируемых переменных в виде значения ключей и для каждой итерации просто замените строку, содержащую a,$<<key>>
на ее<<value>>
.perl -pi -e 'foreach $key(sort keys %ENV){ s/\$$key/$ENV{$key}/g}' file
Предостережение: дополнительная логическая обработка требуется для случаев, когда две или более переменных начинаются с одной и той же строки ...
источник
envsubst
похоже, именно то, что я хотел использовать, но-v
вариант меня немного удивил.Пока
envsubst < template.txt
работал нормально, то же самое с опцией-v
не работало:Как я уже писал, это не сработало:
Мне пришлось сделать это, чтобы он заработал:
Может кому поможет.
источник