Ответ 1
Посмотрев, в моей системе оказывается команда envsubst
, которая является частью пакета gettext-base.
Итак, это упрощает:
envsubst < "source.txt" > "destination.txt"
У меня есть несколько текстовых файлов, в которые я ввел переменные оболочки (например, $VAR1 или $VAR2).
Я хотел бы взять эти файлы (один за другим) и сохранить их в новых файлах, где все переменные были бы заменены.
Для этого я использовал следующую оболочку script (найденную в StackOverflow):
while read line
do
eval echo "$line" >> destination.txt
done < "source.txt"
Это очень хорошо работает в основных файлах.
Но в более сложных файлах команда "eval" делает слишком много:
Линии, начинающиеся с "#", пропускаются
Результаты анализа XML файлов в тоннах ошибок
Есть ли лучший способ сделать это? (в оболочке script... Я знаю, что это легко сделать с помощью Ant)
С уважением
Посмотрев, в моей системе оказывается команда envsubst
, которая является частью пакета gettext-base.
Итак, это упрощает:
envsubst < "source.txt" > "destination.txt"
В ответ на ответ 2 при обсуждении envsubst вы спросили: "Как я могу заставить его работать с переменными, объявленными в моем .sh script?"
Ответ: вам просто нужно экспортировать переменные перед вызовом 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' соответственно.
Я знаю, что эта тема старая, но у меня есть более простое рабочее решение без экспорта переменных. Может быть односложным, но я предпочитаю разделять, используя \
on end.
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
$ cat out.txt
и вы должны увидеть "поздравление".
Если вы действительно хотите использовать bash (и sed), то я бы прошел через каждую из ваших переменных среды (возвращаемых set
в режиме posix) и создав кучу -e 'regex'
для sed из что, завершение с помощью -e 's/\$[a-zA-Z_][a-zA-Z0-9_]*//g'
, затем передать все это в sed.
Perl выполнил бы более приятную работу, но у вас есть доступ к окружению vars в виде массива, и вы можете выполнять исполняемые замены, чтобы один раз сопоставлять только одну переменную среды.
На самом деле вам нужно сменить read
на read -r
, который заставит его игнорировать обратную косую черту.
Кроме того, вам следует избегать цитат и обратных косых черт. Так
while read -r line; do
line="${line//\\/\\\\}"
line="${line//\"/\\\"}"
line="${line//\`/\\\`}"
eval echo "\"$line\""
done > destination.txt < source.txt
Тем не менее ужасный способ сделать расширение, хотя.
envsubst
похоже на то, что я хотел использовать, но опция -v
меня немного удивила.
В то время как envsubst < template.txt
работал нормально, то же самое с опцией -v
не работал:
$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.1 (Maipo)
$ envsubst -V
envsubst (GNU gettext-runtime) 0.18.2
Copyright (C) 2003-2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Bruno Haible.
Как я уже писал, это не работает:
$ envsubst -v < template.txt
envsubst: missing arguments
$ cat template.txt | envsubst -v
envsubst: missing arguments
Я должен был сделать это, чтобы он работал:
TEXT=`cat template.txt`; envsubst -v "$TEXT"
Может быть, это помогает кому-то.
Экспортируйте все необходимые переменные и затем используйте perl onliner
TEXT=$(echo "$TEXT"|perl -wpne 's#\${?(\w+)}?# $ENV{$1}//$& #ge;')
Это заменит все переменные ENV, присутствующие в TEXT, фактическими значениями. Цитаты тоже сохранились :)