Я хочу передать вывод файла "шаблона" в MySQL, файл с переменными типа ${dbName} вкраплен. Что такое утилита командной строки для замены этих экземпляров и выгрузка вывода на стандартный вывод?
Как заменить ${} заполнители в текстовом файле?
Ответ 1
Sed!
Данный файл template.txt:
The number is ${i}
The word is ${word}
мы просто должны сказать:
sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.txt
Спасибо Джонатану Леффлеру за подсказку передать несколько аргументов -e тому же призыву sed.
Ответ 2
Update
Вот решение от yottatsa по аналогичному вопросу, который заменяет только переменные, такие как $VAR или ${VAR}, и представляет собой короткий однострочный
i=32 word=foo envsubst < template.txt
Конечно, если я и слово находятся в вашей среде, то это просто
envsubst < template.txt
На моем Mac это похоже, что он был установлен как часть gettext и из MacGPG2
Старый ответ
Ниже приведено улучшение решения от mogsie по аналогичному вопросу. Мое решение не требует, чтобы вы эскалации двойных кавычек, mogsie, но он один лайнер!
eval "cat <<EOF
$(<template.txt)
EOF
" 2> /dev/null
Сила этих двух решений заключается в том, что вы получаете только несколько типов расширений оболочки, которые обычно не встречаются $((...)), `...` и $(...), хотя обратная косая черта здесь является escape-символом, но вам не нужно беспокоиться о том, что в синтаксическом анализе есть ошибка, и она делает несколько строк просто отлично.
Ответ 3
Используйте /bin/sh. Создайте небольшую оболочку script, которая устанавливает переменные, а затем анализирует шаблон, используя оболочку. Так же (отредактируйте правильную обработку строк перевода):
Файл template.txt:
the number is ${i}
the word is ${word}
Файл script.sh:
#!/bin/sh
#Set variables
i=1
word="dog"
#Read in template one line at the time, and replace variables (more
#natural (and efficient) way, thanks to Jonathan Leffler).
while read line
do
    eval echo "$line"
done < "./template.txt"
Вывод:
#sh script.sh
the number is 1
the word is dog
		Ответ 4
Я думал об этом снова, учитывая недавний интерес, и я думаю, что инструмент, о котором я изначально думал, был m4, макропроцессор для autotools. Поэтому вместо переменной, которую я изначально указал, вы должны использовать:
$echo 'I am a DBNAME' | m4 -DDBNAME="database name"
		Ответ 5
template.txt
Variable 1 value: ${var1}
Variable 2 value: ${var2}
data.sh
#!/usr/bin/env bash
declare var1="value 1"
declare var2="value 2"
parser.sh
#!/usr/bin/env bash
# args
declare file_data=$1
declare file_input=$2
declare file_output=$3
source $file_data
eval "echo \"$(< $file_input)\"" > $file_output
./parser.sh data.sh template.txt parsed_file.txt
parsed_file.txt
Variable 1 value: value 1
Variable 2 value: value 2
		Ответ 6
здесь мое решение с perl на основе прежнего ответа заменяет переменные среды:
perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1}?$ENV{$1}:"missing variable $1")/eg' < infile > outfile
		Ответ 7
Если вы открыты для использования Perl, это будет мое предложение. Хотя есть, вероятно, некоторые sed и/или AWK, которые, вероятно, знают, как сделать это намного проще. Если у вас более сложное сопоставление с более чем просто dbName для ваших замещений, вы могли бы расширить это довольно легко, но вы могли бы также добавить его в стандартный Perl script в этот момент.
perl -p -e 's/\$\{dbName\}/testdb/s' yourfile | mysql
Короткий Perl script сделать что-то немного сложнее (обрабатывать несколько ключей):
#!/usr/bin/env perl
my %replace = ( 'dbName' => 'testdb', 'somethingElse' => 'fooBar' );
undef $/;
my $buf = <STDIN>;
$buf =~ s/\$\{$_\}/$replace{$_}/g for keys %replace;
print $buf;
Если вы назвали вышеуказанный script как replace- script, его можно было бы использовать следующим образом:
replace-script < yourfile | mysql
		Ответ 8
Здесь  надежная Bash функция, которая, несмотря на использование eval, должна быть безопасной.
Все ссылки ${varName} переменных во входном тексте расширены на основе переменных вызывающей оболочки.
Ничего другого не раскрывается: ни ссылки на переменные, имена которых не заключены в {...} (например, $varName), ни подстановки команд ($(...) и устаревший синтаксис `...`), ни арифметические подстановки ($((...)) и устаревший синтаксис $[...]).
Чтобы обработать a $ как литерал, \ -escape it; например:. \${HOME}
Обратите внимание, что вход принимается только через stdin.
Пример:
$ expandVarsStrict <<<'$HOME is "${HOME}"; `date` and \$(ls)' # only ${HOME} is expanded
$HOME is "/Users/jdoe"; `date` and $(ls)
Исходный код функции:
expandVarsStrict(){
  local line lineEscaped
  while IFS= read -r line || [[ -n $line ]]; do  # the `||` clause ensures that the last line is read even if it doesn't end with \n
    # Escape ALL chars. that could trigger an expansion..
    IFS= read -r -d '' lineEscaped < <(printf %s "$line" | tr '`([$' '\1\2\3\4')
    # ... then selectively reenable ${ references
    lineEscaped=${lineEscaped//$'\4'{/\${}
    # Finally, escape embedded double quotes to preserve them.
    lineEscaped=${lineEscaped//\"/\\\"}
    eval "printf '%s\n' \"$lineEscaped\"" | tr '\1\2\3\4' '`([$'
  done
}
  Функция предполагает, что во входном элементе присутствуют управляющие символы 0x1, 0x2, 0x3 и 0x4, потому что эти символы. используются внутри - поскольку функция обрабатывает текст, это должно быть безопасным предположением.
Ответ 9
Создать rendertemplate.sh:
#!/usr/bin/env bash
eval "echo \"$(cat $1)\""
И template.tmpl:
Hello, ${WORLD}
Goodbye, ${CHEESE}
Выделите шаблон:
$ export WORLD=Foo
$ CHEESE=Bar ./rendertemplate.sh template.tmpl 
Hello, Foo
Goodbye, Bar
		Ответ 10
file.tpl:
The following bash function should only replace ${var1} syntax and ignore 
other shell special chars such as `backticks` or $var2 or "double quotes". 
If I have missed anything - let me know.
script.sh:
template(){
    # usage: template file.tpl
    while read -r line ; do
            line=${line//\"/\\\"}
            line=${line//\`/\\\`}
            line=${line//\$/\\\$}
            line=${line//\\\${/\${}
            eval "echo \"$line\""; 
    done < ${1}
}
var1="*replaced*"
var2="*not replaced*"
template file.tpl > result.txt
		Ответ 11
Я бы предложил использовать что-то вроде Sigil: https://github.com/gliderlabs/sigil
Он скомпилирован в один бинарный файл, поэтому его очень легко установить в системах.
Затем вы можете сделать простой однострочный слой следующим образом:
cat my-file.conf.template | sigil -p $(env) > my-file.conf
Это намного безопаснее, чем eval, и проще, используя регулярное выражение или sed
Ответ 12
Я нашел эту ветку, задаваясь вопросом то же самое. Это вдохновило меня на это (осторожно с обратными окнами)
$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world
		Ответ 13
Здесь много вариантов, но я понял, что я брошу свою кучу. Это perl based, только целевые переменные формы ${...}, обрабатывает файл как аргумент и выводит преобразованный файл на stdout:
use Env;
Env::import();
while(<>) { $_ =~ s/(\${\w+})/$1/eeg; $text .= $_; }
print "$text";
Конечно, я на самом деле не человек perl, поэтому легко может быть фатальный недостаток (работает для меня, хотя).
Ответ 14
Это можно сделать в bash, если вы управляете форматом файла конфигурации. Вам просто нужно указать ( "." ) Файл конфигурации, а не подстроить его. Это гарантирует, что переменные создаются в контексте текущей оболочки (и продолжают существовать), а не подоболочки (где переменная исчезает, когда подоболочка выходит).
$ cat config.data
    export parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA
    export parm_user=pax
    export parm_pwd=never_you_mind
$ cat go.bash
    . config.data
    echo "JDBC string is " $parm_jdbc
    echo "Username is    " $parm_user
    echo "Password is    " $parm_pwd
$ bash go.bash
    JDBC string is  jdbc:db2://box7.co.uk:5000/INSTA
    Username is     pax
    Password is     never_you_mind
Если ваш файл конфигурации не может быть оболочкой script, вы можете просто "скомпилировать" его перед выполнением (компиляция зависит от вашего формата ввода).
$ cat config.data
    parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA # JDBC URL
    parm_user=pax                              # user name
    parm_pwd=never_you_mind                    # password
$ cat go.bash
    cat config.data
        | sed 's/#.*$//'
        | sed 's/[ \t]*$//'
        | sed 's/^[ \t]*//'
        | grep -v '^$'
        | sed 's/^/export '
        >config.data-compiled
    . config.data-compiled
    echo "JDBC string is " $parm_jdbc
    echo "Username is    " $parm_user
    echo "Password is    " $parm_pwd
$ bash go.bash
    JDBC string is  jdbc:db2://box7.co.uk:5000/INSTA
    Username is     pax
    Password is     never_you_mind
В вашем конкретном случае вы можете использовать что-то вроде:
$ cat config.data
    export p_p1=val1
    export p_p2=val2
$ cat go.bash
    . ./config.data
    echo "select * from dbtable where p1 = '$p_p1' and p2 like '$p_p2%' order by p1"
$ bash go.bash
    select * from dbtable where p1 = 'val1' and p2 like 'val2%' order by p1
Затем подключите вывод go.bash к MySQL и voila, надеюсь, вы не уничтожите свою базу данных: -).