3

是否有可能在我 cat 文件时以一种干净的方式获取变量值,而不是文件中写入的变量名。这很难解释,但这里有一个简单的例子:

$ cat <<EOF
$HOME
EOF
/home/myself

cat 返回 /home/myself 因为它已经被 shell 扩展了。

$ echo \$HOME >/tmp/home
$ cat /tmp/home
$HOME

cat 只是读取文件,我希望通过 cat 以某种方式在此处扩展 $HOME,因为该文件将包含变量名(不像 HOME=/home/myself)

我的问题是这是否可能以某种方式实现,否则我将不得不编写一些脏代码。

编辑:它们是包含的大 xml 文件

<checkbox active="$value">

对或错

4

4 回答 4

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
于 2011-05-17T01:57:20.970 回答
1

cat将其输入原封不动地复制到其输出 - 至少以原始(第 1 版 UNIX)形式。它没有任何选择开始。然后 BSD 添加了一堆,原始 UNIX 团队反对:'cat从伯克利挥舞旗帜回来'(参见:1 - passim)。它不应该用于编辑文件——这不是它的目的。(我在 BSD (Mac OS X) 手册页中找到了对以下文章的引用cat:Rob Pike,“UNIX 风格或 cat -v 被认为是有害的”,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;
}

当我在捕获中包含文字$时,替代操作无法正常工作。

于 2011-05-17T02:43:46.463 回答
1

这样做的明显方法有很多问题:

# 这会因某些输入而失败。HTML肯定会出问题
# 因为 '<' 和 '>' 字符将被解释为文件重定向
$ 同时读取 r; 做评估回声$ r; 完成<输入

下面的 perl 应该可以很好地处理简单输入的问题。

$ perl -pwe 'while(($k,$v) = each %ENV) { s/\${?$k}?/$v/ }' 输入

但它对 ${FOO-bar} 之类的结构没有任何作用。如果您需要处理此类构造,则转义所有 shell 元字符并执行 while/read 循环可能就足够了:

$ sed -e 's/\([<>&|();]\)/\\\1/g' 输入 | 同时读取-rl;执行 eval echo "$l"; 完毕

请注意,这既不可靠也不安全。考虑一下输入会发生什么,例如:

\; rm -rf /

我说“考虑”。不要测试那个。sed 会在分号前插入一个反斜杠,然后 eval 会得到字符串 "\\;" 这将被解释为单个反斜杠,后跟一个分号,终止回显,并且 rm -rf 将被执行。鉴于评估未知输入的不安全性,坚持使用 perl 之类的东西并明确替换所需的 sh 构造可能会更安全。就像是:

$ perl -pwe 'while(($k,$v) = each %ENV) { s/\${?$k}?/$v/ };
    s/\${[^-]*-([^}]*)}/$1/g' 输入

这个输入有问题,如 ${FOO=some-text}。为了可靠地获取所有 sh 构造(${word:rhs},其中 ':' 可以是 '-'、'?'、'='、'+'、'%'、'#' 或任何带有冒号的相同(或许多其他符号,如果您允许非posix sh 语法!))您将不得不构建一组相当精细的比较。

于 2011-05-17T13:08:20.377 回答
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
于 2021-02-25T21:02:41.127 回答