0

假设我有一个模板文本文件,其中大部分内容是静态的,但有一些变量。例如

My favorite site is ${FAV_SITE}

假设 FAV_SITE 设置为 stackoverflow.com:

export FAV_SITE=stackoverflow.com

如何将解析了 vars 的文件内容打印到 STDOUT,即

My favorite site is stackoverflow.com

不使用 sed 或 awk 等花哨的工具?

4

4 回答 4

2

这是完成这项工作的几乎微不足道的 Perl 部分。

#!/usr/bin/env perl
#
# Substitute environment variables into text

use strict;
use warnings;

while (<>)
{
    while (m/\${(\w+)}/g)
    {
        my $env = $1;
        if (defined $ENV{$env})
        {
            my $sub = $ENV{$env};
            s/\${$env}/$sub/g;
        }
    }
    print;
}

如果未定义环境变量,则${VARIABLE}符号保持不变。

例如,在输入数据上:

This is ${HOME} and so is this (${HOME}) and that's ${USER} and that's all.
This is ${UNDEFINED} and that is ${UNDEF} too.

输出可能是:

This is /work4/jleffler and so is this (/work4/jleffler) and that's jleffler and that's all.
This is ${UNDEFINED} and that is ${UNDEF} too.

Perl 可能没有它应该的那么紧凑,但是如果您知道读取操作符<>和匹配、替换和打印操作符在默认变量$_.


在 RHEL 5 Linux(不要问)上使用 Perl 5.12.1(自制),我使用:

$ cat x3 
This is ${UNDEFINED} and that is ${UNDEF} too.
This is ${HOME} and so is this (${HOME}) and that's ${USER} and that's all.
$ perl subenv.pl x3
This is ${UNDEFINED} and that is ${UNDEF} too.
This is /work4/jleffler and so is this (/work4/jleffler) and that's jleffler and that's all.
$

如果您使用此处的文档创建模板,请小心;shell 也会扩展这些变量。

我还在/usr/bin/perlRHEL 机器上找到了 Perl 5.8.8,它产生了相同的输出。我还检查了 Mac OS X 10.7.5 上的 Perl 5.16.0,以及相应的结果(不同的主目录)。我还在 HP-UX 11.00 机器上找到了一个 Perl 5.6.1,${USER}它没有在环境中设置,但它被${HOME}正确替换了。

于 2012-10-02T22:46:05.860 回答
1

您可以将模板文件制作成 bash 脚本吗?

#!/bin/bash
# This is a template, execute it to get interpolated text:
cat <<HERE
My favorite site is ${FAV_SITE}
HERE

使用示例:

export FAV_SITE=stackoverflow.com
bash ./template.txt.sh

(哦,你可能需要访问 reddit.com)

于 2012-10-02T22:21:31.083 回答
0

使用 Perl:

#!/usr/bin/perl

use strict;

my $inFile = $ARGV[0];

print "\nInput File=".$inFile;

open(FILEHANDLE, "<$inFile") || die("Could not open file");

my @fileLines = <FILEHANDLE>;

my $rslt;

foreach my $line(@fileLines)
{
    #chomp($line);

    #print "\nLINE BEFORE=".$line;

    while($line =~ m/(\${\w+})/g)
    {
        if($1)
        {
            my $plchldr = $1;

            my $varName = $plchldr;

            $varName =~ s/(\$|{|})//g;

            my $varVal = $ENV{$varName};

            if($varVal)
            {
                $line =~ s/\Q$plchldr/$varVal/g;
            }
        }
    }

    $rslt .= $line;

    #print "\nLINE AFTER=".$line;
}

print "\nRESULT = ".$rslt;

close(FILEHANDLE);

print "\n";

exit(0);
于 2012-10-03T16:31:32.057 回答
0

Always be wary of eval, but:

while read l; do eval echo "\"$l\""; done < input-file

Only use this if you control the input. For example, if the input contains a line like "; rm -rf /" it would be most unfortunate to run this script.

于 2012-10-02T23:08:52.510 回答