Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在键入文件时获取替换的变量_Bash_Shell_Variables_Sh_Cat - Fatal编程技术网

Bash 在键入文件时获取替换的变量

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时,是否有可能以干净的方式获取变量值,而不是像文件中所写的那样获取变量名。这很难解释,但这里有一个简单的例子:

$ 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