Bash 在键入文件时获取替换的变量
当我对文件进行cat时,是否有可能以干净的方式获取变量值,而不是像文件中所写的那样获取变量名。这很难解释,但这里有一个简单的例子:Bash 在键入文件时获取替换的变量,bash,shell,variables,sh,cat,Bash,Shell,Variables,Sh,Cat,当我对文件进行cat时,是否有可能以干净的方式获取变量值,而不是像文件中所写的那样获取变量名。这很难解释,但这里有一个简单的例子: $ cat <<EOF $HOME EOF /home/myself cat只是读取文件,我希望$HOME在这里以某种方式由cat展开,因为该文件将包含变量名(不像HOME=/HOME/MY本人) 我的问题是,这是否可能,否则我将不得不编写一些肮脏的代码 编辑:它们是包含 <checkbox active="$value"> true
$ cat <<EOF
$HOME
EOF
/home/myself
cat只是读取文件,我希望$HOME在这里以某种方式由cat展开,因为该文件将包含变量名(不像HOME=/HOME/MY本人)
我的问题是,这是否可能,否则我将不得不编写一些肮脏的代码
编辑:它们是包含
<checkbox active="$value">
true或false在Python中尝试这一点很简单,看看这是否适用于您。通过调用执行转换的函数(而不是用特定字符串替换),可以使用该函数替换某些模式(如
“\$\w+”
)。对于替换函数,您可以使用os.getenv()
,它当然接受变量名并返回其值
编辑:这里有一个完整的Python脚本,可以执行上述操作:
#!/usr/bin/python
import fileinput
import os
import re
def transform(match):
return os.getenv(match.group(1)) # replace the "capture" to omit $
for line in fileinput.input(): # reads from stdin or from a file in argv
print re.sub('\$(\w+)', transform, line), # comma to omit newline
cat
将其输入原封不动地复制到其输出-至少以其原始(第一版UNIX)形式复制。它一开始没有任何选择。然后BSD添加了一组,最初的UNIX团队反对:“cat
从伯克利回来挥舞着旗帜”(参见:-passim)。它不应该被用来编辑文件-这不是它的目的。(我在BSD(Mac OS X)手册页上找到了一篇文章,内容是关于cat
:Rob Pike,“UNIX风格,或被认为有害的cat-v”,USENIX Summer Conference Proceedings,1983年。另见)
因此,您需要的不是cat
来完成这项工作。我推荐Perl或Python;两者都可以很容易地做到。或者,考虑<代码> SED,或者可能是<代码> AWK < /P>
#!/usr/bin/env perl
use strict;
use warnings;
while (<>)
{
foreach my $key (keys %ENV)
{
s/\$$key\b/$ENV{$key}/g; # $envvar
s/\${$key}/$ENV{$key}/g; # ${envvar}
}
print;
}
#/usr/bin/env perl
严格使用;
使用警告;
而()
{
foreach my$密钥(密钥%ENV)
{
s/\$$key\b/$ENV{$key}/g;#$envvar
s/\${$key}/$ENV{$key}/g;#${envvar}
}
印刷品;
}
这将循环输入行,依次查找每个环境变量。另一种机制是寻找可能的变量并进行相关的替换。这有点棘手,但可行:
#!/usr/bin/env perl
use strict;
use warnings;
while (<>)
{
while (m/\$((\w+))/ || m/\$({(\w+)})/)
{
my $key = $2;
my $var = $1;
s/\$$var/$ENV{$key}/g if defined $ENV{$key};
}
print;
}
#/usr/bin/env perl
严格使用;
使用警告;
而()
{
而(m/\$(\w+)/| m/\$({(\w+)})/)
{
我的$key=$2;
my$var=$1;
s/\$$var/$ENV{$key}/g(如果定义为$ENV{$key});
}
印刷品;
}
当我在捕获中包含文字
$
时,替换操作无法正常工作。执行此操作的明显方法有很多问题:
# This will fail with certain inputs. HTML will certainly be a problem
# as the '<' and '>' characters will be interpreted as file redirects
$ while read r; do eval echo $r; done < input
#这将在某些输入下失败。HTML肯定会成为一个问题
#因为“”字符将被解释为文件重定向
$whilereadr;评估回声$r;完成<输入
对于简单的输入,下面的perl应该可以很好地处理这个问题
$ perl -pwe 'while(($k,$v) = each %ENV ) { s/\${?$k}?/$v/ }' input
$perl-pwe'while($k,$v)=每个%ENV){s/\${?$k}?/$v/}输入
但是它对${foobar}这样的结构没有任何作用。如果需要处理此类构造,则转义所有shell元字符并执行while/read循环就足够了:
$ sed -e 's/\([<>&|();]\)/\\\1/g' input | while read -r l; do eval echo "$l"; done
$sed-e's/\([&|();]\)/\\\1/g'输入,而read-r-l;进行评估回音“$l”;完成
请注意,这既不健壮也不安全。考虑输入上发生的事情:
\; rm -rf /
\; rm-rf/
我说“考虑”。不要测试它。sed将在分号之前插入一个反斜杠,eval将获得字符串“\\;”,该字符串将被解释为一个反斜杠,后跟一个分号,该分号表示回音,并且将执行rm-rf。考虑到评估未知输入的不安全性,使用perl之类的工具并显式替换所需的sh结构可能会更安全。比如:
$ perl -pwe 'while(($k,$v) = each %ENV ) { s/\${?$k}?/$v/ };
s/\${[^-]*-([^}]*)}/$1/g' input
$perl-pwe'while($k,$v)=每个%ENV){s/\${?$k}?/$v/};
s/\${[^-]*-([^}]*)}/$1/g'输入
这一个在输入方面有问题,比如${FOO=some text}。为了可靠地获取所有sh构造(${word:rhs},其中“:”可以是“-”、“?”、“=”、“+”、“%”、“#”中的任意一个,或者前面加了冒号(如果允许非posix sh语法,则可以是许多其他符号!))您必须构建一个相当复杂的比较集。我最近发现了一种使用
envsubt
的方法:
export MYNAME="Jason"
echo '{ "status": 200, "message": { "name": "$MYNAME" } }' > my.json.template
cat my.json.template
# outputs { "status": 200, "message": { "name": "$MYNAME" } }
cat my.json.template | envsubst
# outputs { "status": 200, "message": { "name": "Jason" } }
如果您没有envsubt
,可以通过以下方式将其安装在debian发行版上:
apt-get install gettext-base
echo`cat/tmp/home`
?只有一个变量名?或者你是在尝试开发某种形式的模板引擎,将变量值插入到自由格式文本中?Beta@nay。。。;sarnold@big xml文件包含“”true或false。我将从/etcharly中的其他文件中获取值。我将很快为您编写代码,您将看到它是多么简单。是的,我查看了cat手册页,它只是为了读取文件而设计的,尽管它可以用于编写带有重定向的文件。你的剧本也很好,谢谢!我就是这么想的。如果我使用sed命令,我可以使用所有bash构造(我是一种bash主义者,在这些脚本中,可移植性不是问题)。我在sed命令中发现的问题是,所有双引号,即\“,都会消失。XML需要active=“true”,并且在active=true时失败。我需要保留XML中的引号,因为许多引号都不包含变量。我们如何改进此sed命令?@Teresa只需在要转义的字符列表中添加一个”就可以了。不过,我想我还是坚持使用perl,因为评估未知输入可能会带来非常严重的后果。
apt-get install gettext-base