是否有可能以一种干净的方式在我捕获文件时获取变量值,而不是在文件中写入的变量名。这很难解释,但这里有一个简单的例子:
$ cat <<EOF
$HOME
EOF
/home/myself
cat返回/ home /我,因为它已经被shell扩展了。
$ echo \$HOME >/tmp/home
$ cat /tmp/home
$HOME
cat只是读取文件,我想通过cat以某种方式将$ HOME扩展到此处,因为该文件将包含变量名称(不像HOME = / home / myself)
我的问题是,这是否可能以某种方式,否则我将不得不写一些脏代码。
编辑:它们是包含
的大型xml文件<checkbox active="$value">
是或否
答案 0 :(得分:2)
在Python中尝试这是微不足道的,看看它是否适合你。您可以使用re.sub函数通过调用执行转换的函数(而不是替换它的特定字符串)来替换某些模式(例如"\$\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
答案 1 :(得分:1)
cat
将其输入不变地复制到其输出 - 至少在其原始(第1版UNIX)表单中。它没有任何选择。然后BSD增加了一堆,最初的UNIX团队反对:'cat
从伯克利挥手挥舞旗帜回来了(参见:1 - passim)。它不应该用于编辑文件 - 这不是它的目的。 (我找到了对cat
的BSD(Mac OS X)手册页中的文章的引用:Rob Pike,“UNIX Style,或者cat -v Considered Harmful”,USENIX夏季会议诉讼程序,1983年。另见http://quotes.cat-v.org/programming/)
因此,您需要cat
以外的其他工作来完成这项工作。我推荐Perl或Python;要么可以很容易地做到这一点。或者,请考虑sed
,或者awk
。
#!/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
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;
}
当我在捕获中包含文字$
时,替换操作无效。
答案 2 :(得分:1)
显而易见的方法有很多问题:
# 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
以下perl应该能够很好地处理简单输入的问题。
$ perl -pwe 'while(($k,$v) = each %ENV ) { s/\${?$k}?/$v/ }' input
但它对$ {FOO-bar}这样的结构没有任何作用。如果你需要处理这样的结构,可能就足以转义所有的shell元字符并执行while / read循环:
$ sed -e 's/\([<>&|();]\)/\\\1/g' input | while read -r l; do eval echo "$l"; done
请注意,这既不健壮也不安全。考虑在输入上发生的事情,如:
\; rm -rf /
我说“考虑”。不要测试。 sed将在分号前插入反斜杠,然后eval将获得字符串“\\;”这将被解释为单个反斜杠后跟一个分号终止回声,并且将执行rm -rf。鉴于评估未知输入的不安全性,坚持像perl这样的东西并明确地替换所需的sh构造可能更安全。类似的东西:
$ perl -pwe 'while(($k,$v) = each %ENV ) { s/\${?$k}?/$v/ }; s/\${[^-]*-([^}]*)}/$1/g' input
这个输入有问题,比如$ {FOO = some-text}。为了可靠地获取所有sh构造($ {word:rhs},其中':'可以是' - ','?','=','+','%','#'或任何相同的冒号前缀(或许多其他符号,如果你允许非posix sh语法!))你将不得不构建一个相当精细的比较集。
答案 3 :(得分:1)
我最近找到了一种使用 envsubst
执行此操作的方法:
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" } }
如果您没有 envsubst
,您可以在 debian 发行版上安装它:
apt-get install gettext-base