6

Я хотел бы как-нибудь выложить файл (в котором есть ссылки на переменные env) и подставить фактические значения. Это то, что я пробовал, но, как вы можете видеть, это не работает. Есть идеи?

-bash-3.00$ cat vars_file 
${MY_VAR}
-bash-3.00$ export MY_VAR=MY_VALUE; cat ./vars_file | xargs echo
${MY_VAR}

6 ответов6

9

Старый поток, но это повторяющаяся проблема. Вот решение с использованием bash- mapfile:

mateus@mateus:/tmp$ cat input.txt
a = $a
b = $b
mateus@mateus:/tmp$ echo a=$a, b=$b
a=1, b=2
mateus@mateus:/tmp$ function subst() { eval echo -E "$2"; }
mateus@mateus:/tmp$ mapfile -c 1 -C subst < input.txt
a = 1
b = 2

Встроенный в bash mapfile вызывает пользовательскую функцию subst (см. Опции -C/-c) в каждой строке, считываемой из входного файла input.txt . Поскольку строка содержит неэкранированный текст, используется eval его оценки и echo преобразованного текста в стандартный вывод (-E избегать интерпретации специальных символов).

ИМХО, это гораздо более элегантно, чем любое решение на основе sed/awk/perl/regex.

Другое возможное решение - использовать собственную подстановку оболочки. Это выглядит как более "переносимый" способ не передавать на mapfile:

mateus@mateus:/tmp$ EOF=EOF_$RANDOM; eval echo "\"$(cat <<$EOF
$(<input.txt)
$EOF
)\""
a = 1
b = 2

Обратите внимание, что мы используем $EOF чтобы минимизировать конфликтующие здесь документы cat с содержимым input.txt.

Оба примера из: https://gist.github.com/4288846

РЕДАКТИРОВАТЬ: Извините, первый пример не обрабатывает комментарии и пробелы правильно. Я поработаю над этим и выложу решение. EDIT2: исправление двойного случайного $ eval

2

Может быть сделано с помощью скрипта (например, имя файла является expand.sh):

while read line; do eval echo \"$line\"; done < $1 > $2

Сценарий можно назвать так:

env VAR1=value1 sh expand.sh input_file output_file

- http://www.issociate.de/board/post/281806/sed_replace_by_enviroment_var_content.html

2

Как описано в том же потоке на http://www.issociate.de/board/post/281806/sed_replace_by_enviroment_var_content.html, "правильное" решение будет следующим:

awk '{while(match($0,"[$]{[^}]*}")) {var=substr($0,RSTART+2,RLENGTH -3);gsub("[$]{"var"}",ENVIRON[var])}}1' < input.txt > output.txt

Подход eval хорош, но, как правило, не работает с файлами XML.

1

Вот мое предлагаемое решение:

eval $'cat <<\002\n'"$(<ifile)"$'\n\002' > ofile

\002 можно заменить любым символом или строкой, которых нет в ifile. Чтобы удалить любые вхождения символа-разделителя во входном файле:

eval $'cat <<\002\n'"$(tr -d '\002' < ifile)"$'\n\002' > ofile

Это решение, похоже, решает большинство проблем, но особенно уязвимо для внедрения команд в файл шаблона через директивы $(command) .

1

$"xxx" может быть простым способом

a=$(< file)
eval b=\$\"$a\"

тогда "$ b" - это расширенный текст

0

Это определяет функцию оболочки, которая использует python для имитации базового расширения оболочки переменных $ {name}. Я использую его для расширения переменных bash, встроенных в сценарии sql. Поскольку мой файл не является истинным файлом bash, вы не можете использовать встроенную функцию eval() bash

apply_shell_expansion() {
python - << EOF
import os
doc=open('${1}').read()
for k,v in os.environ.items():
  doc = doc.replace('$'+'{'+k+'}',v)
print doc
EOF
}

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .