Reputation: 31278
Let's say I have a template text file most of whose content is static but has some variables. E.g.
My favorite site is ${FAV_SITE}
Let's say that FAV_SITE is set to stackoverflow.com:
export FAV_SITE=stackoverflow.com
How do I print to STDOUT the contents of the file with the vars resolved, i.e.
My favorite site is stackoverflow.com
without using fancy tools like sed or awk?
Upvotes: 0
Views: 291
Reputation: 31278
Using 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);
Upvotes: 0
Reputation: 754540
This is an almost trivial bit of Perl that does the job.
#!/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;
}
If the environment variable is not defined, it leaves the ${VARIABLE}
notation unchanged.
For example, on the input data:
This is ${HOME} and so is this (${HOME}) and that's ${USER} and that's all.
This is ${UNDEFINED} and that is ${UNDEF} too.
the output might be:
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.
The Perl probably isn't as compact is it could be, but it is more or less comprehensible if you know that the read operator <>
and the match, substitute and print operators work on the default variable, $_
.
Using Perl 5.12.1 (home-built) on RHEL 5 Linux (don't ask), I used:
$ 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.
$
Just be careful if you create the template with a here document; the shell will expand those variables too.
I also found Perl 5.8.8 in /usr/bin/perl
on the RHEL machine and that produced the same output. I also checked Perl 5.16.0 on Mac OS X 10.7.5, with the corresponding result (different home directory). I also found a Perl 5.6.1 on a HP-UX 11.00 machine where ${USER}
was not set in the environment, but it substituted ${HOME}
correctly.
Upvotes: 2
Reputation: 212434
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.
Upvotes: 0
Reputation: 393537
Can you make the template file a bash script?
#!/bin/bash
# This is a template, execute it to get interpolated text:
cat <<HERE
My favorite site is ${FAV_SITE}
HERE
Example of use:
export FAV_SITE=stackoverflow.com
bash ./template.txt.sh
(oh and you might need to visit reddit.com)
Upvotes: 1