我想将一个包含像
${dbName}
这样的变量的“模板”文件的输出导入到MySQL中。有什么命令行工具可以替换这些实例并将输出转储到标准输出?输入文件被认为是安全的,但可能存在错误的替换定义。执行替换应避免执行意外的代码执行。${dbName}
这样的变量的“模板”文件的输出导入到MySQL中。有什么命令行工具可以替换这些实例并将输出转储到标准输出?输入文件被认为是安全的,但可能存在错误的替换定义。执行替换应避免执行意外的代码执行。如果您愿意使用Perl,那将是我的建议。虽然可能有一些sed和/或AWK专家知道如何更轻松地完成此操作。如果您有一个更复杂的映射,不仅仅是用于替换dbName,您可以很容易地扩展它,但在那时,您也可以将其放入标准的Perl脚本中。
perl -p -e 's/\$\{dbName\}/testdb/s' yourfile | mysql
#!/usr/bin/env perl
my %replace = ( 'dbName' => 'testdb', 'somethingElse' => 'fooBar' );
undef $/;
my $buf = <STDIN>;
$buf =~ s/\$\{$_\}/$replace{$_}/g for keys %replace;
print $buf;
replace-script < yourfile | mysql
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
\$(date)
,它将会被执行。 - Peter Dolbergwhile IFS= read -r line; do
作为read
命令,否则您将从每个输入行中剥离前导和尾随空格。此外,echo
可能会将一行的开头误认为是其命令行选项之一,因此最好使用printf '%s\n'
。
最后,最好对${1}
进行双引号。 - mklement0$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world
$(cat file)
的Bash快捷方式是 $(< file)
。 - glenn jackmaneval echo "\"$(cat FILE)\""
,但是输入中的双引号可能仍然会被丢弃。 - mklement0\
…` 或
$(…))由于使用了
eval`,允许执行任意命令。 - mklement0这里有很多选择,但我想分享我的。它是基于Perl的,只针对形如${...}的变量,将要处理的文件作为参数,并将转换后的文件输出到标准输出:
use Env;
Env::import();
while(<>) { $_ =~ s/(\${\w+})/$1/eeg; $text .= $_; }
print "$text";
Env::import();
行 - 导入已经被 use
隐含了。此外,我建议不要先在内存中构建整个输出:只需在循环内使用 print;
而不是 $text .= $_;
,并删除循环后的 print
命令。 - mklement0如果您可以控制配置文件的格式,那么可以在bash本身中完成此操作。您只需要通过源代码(".")来读取配置文件,而不是作为子shell来执行它。这可以确保变量是在当前shell的上下文中创建(并继续存在),而不是在子shell中(变量在子shell退出时会消失)。
$ 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
$ 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 中,完成了,希望你不会破坏你的数据库 :-).
go.bash
)中的回显语句,那么你可能误解了 - 它们不是解决方案的一部分,只是一种展示变量被正确设置的方式。 - paxdiablo对我来说,这是最简单和最强大的解决方案,您甚至可以使用相同的命令eval echo "$(<template.txt)
包含其他模板:
嵌套模板示例
${VARIABLE_NAME}
或$VARIABLE_NAME
在模板中必须使用
\
转义特殊字符,否则它们将被eval
解释。
template.txt
Hello ${name}!
eval echo $(<nested-template.txt)
nested-template.txt
Nice to have you here ${name} :\)
template.source
declare name=royman
source template.source && eval echo "$(<template.txt)"
Hello royman!
Nice to have you here royman :)
使用 Perl 在原位编辑多个文件,并备份。
perl -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : ""/eg' \
-i.orig \
-p config/test/*
envsubst
请不要使用其他任何东西(例如,请勿使用 eval
)
简单用法:
export name="Dana the Sane"
Hello ${name}
envsubst
的标准输入中。envsubst < template.txt
Hello Dana the Sane
envsubst < template.txt > template.txt
不起作用。重定向会在读取之前将输出文件清零。eval
是bash文档中某些用例的推荐方法。 - Eugen Rieckenvsubst
就是你唯一剩下的选择 - 如果你唯一能够使用的工具是锤子,那么所有事物都会看起来像钉子。 - Eugen Rieck我创建了一个名为shtpl
的shell模板脚本。我的shtpl
使用类似于jinja的语法,现在我经常使用ansible,对此非常熟悉:
$ cat /tmp/test
{{ aux=4 }}
{{ myarray=( a b c d ) }}
{{ A_RANDOM=$RANDOM }}
$A_RANDOM
{% if $(( $A_RANDOM%2 )) == 0 %}
$A_RANDOM is even
{% else %}
$A_RANDOM is odd
{% endif %}
{% if $(( $A_RANDOM%2 )) == 0 %}
{% for n in 1 2 3 $aux %}
\$myarray[$((n-1))]: ${myarray[$((n-1))]}
/etc/passwd field #$n: $(grep $USER /etc/passwd | cut -d: -f$n)
{% endfor %}
{% else %}
{% for n in {1..4} %}
\$myarray[$((n-1))]: ${myarray[$((n-1))]}
/etc/group field #$n: $(grep ^$USER /etc/group | cut -d: -f$n)
{% endfor %}
{% endif %}
$ ./shtpl < /tmp/test
6535
6535 is odd
$myarray[0]: a
/etc/group field #1: myusername
$myarray[1]: b
/etc/group field #2: x
$myarray[2]: c
/etc/group field #3: 1001
$myarray[3]: d
/etc/group field #4:
更多关于我的GitHub的信息