Подтвердить что ты не робот

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

У меня есть несколько текстовых файлов, в которые я ввел переменные оболочки (например, $VAR1 или $VAR2).

Я хотел бы взять эти файлы (один за другим) и сохранить их в новых файлах, где все переменные были бы заменены.

Для этого я использовал следующую оболочку script (найденную в StackOverflow):

while read line
do
    eval echo "$line" >> destination.txt
done < "source.txt"

Это очень хорошо работает в основных файлах.

Но в более сложных файлах команда "eval" делает слишком много:

  • Линии, начинающиеся с "#", пропускаются

  • Результаты анализа XML файлов в тоннах ошибок

Есть ли лучший способ сделать это? (в оболочке script... Я знаю, что это легко сделать с помощью Ant)

С уважением

4b9b3361

Ответ 1

Посмотрев, в моей системе оказывается команда envsubst, которая является частью пакета gettext-base.

Итак, это упрощает:

envsubst < "source.txt" > "destination.txt"

Ответ 2

В ответ на ответ 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' соответственно.

Ответ 3

Я знаю, что эта тема старая, но у меня есть более простое рабочее решение без экспорта переменных. Может быть односложным, но я предпочитаю разделять, используя \ 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} который не следует заменять.

Ответ 4

  1. Определите вашу переменную ENV
$ export MY_ENV_VAR=congratulation
  1. Создайте файл шаблона (in.txt) со следующим содержимым
$MY_ENV_VAR

Вы также можете использовать все другие переменные ENV, определенные вашей системой, например (в Linux) $ TERM, $ SHELL, $ HOME...

  1. Запустите эту команду, чтобы заменить все env-переменные в вашем файле in.txt и записать результат в out.txt.
$ envsubst "'printf '${%s} ' $(sh -c "env|cut -d'=' -f1")'" < in.txt > out.txt
  1. Проверьте содержимое файла out.txt
$ cat out.txt

и вы должны увидеть "поздравление".

Ответ 5

Если вы действительно хотите использовать bash (и sed), то я бы прошел через каждую из ваших переменных среды (возвращаемых set в режиме posix) и создав кучу -e 'regex' для sed из что, завершение с помощью -e 's/\$[a-zA-Z_][a-zA-Z0-9_]*//g', затем передать все это в sed.

Perl выполнил бы более приятную работу, но у вас есть доступ к окружению vars в виде массива, и вы можете выполнять исполняемые замены, чтобы один раз сопоставлять только одну переменную среды.

Ответ 6

На самом деле вам нужно сменить read на read -r, который заставит его игнорировать обратную косую черту.

Кроме того, вам следует избегать цитат и обратных косых черт. Так

while read -r line; do
  line="${line//\\/\\\\}"
  line="${line//\"/\\\"}"
  line="${line//\`/\\\`}"
  eval echo "\"$line\""
done > destination.txt < source.txt

Тем не менее ужасный способ сделать расширение, хотя.

Ответ 7

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"

Может быть, это помогает кому-то.

Ответ 8

Экспортируйте все необходимые переменные и затем используйте perl onliner

TEXT=$(echo "$TEXT"|perl -wpne 's#\${?(\w+)}?# $ENV{$1}//$& #ge;')

Это заменит все переменные ENV, присутствующие в TEXT, фактическими значениями. Цитаты тоже сохранились :)