Fabian
Fabian

Reputation: 5650

How do I evaluate shell variables in a string?

In my Perl script I get strings of file paths that may contain environment variables, e.g. $FONTS/test.ttf or $TMP/file.txt.

I now want to open those files like this:

open my $handle, "<$filename" or die $!;

How can I now expand the environment variables prior to the open call, as e.g. the bash shell would do?

Upvotes: 7

Views: 6785

Answers (4)

user3825182
user3825182

Reputation: 31

Why not just do this:

$filename =~ s/\$\{(\w+)\}/$ENV{$1}/g;
$filename =~ s/\$(\w+)/$ENV{$1}/g;

Upvotes: 3

scavenger
scavenger

Reputation: 11

sorry but you are wrong.

to work in perl with SHELL variables, the correct syntax is : $ENV{variable}

example with a colored GCC output function :

n=$(tput setaf 0)
r=$(tput setaf 1)
g=$(tput setaf 2)
y=$(tput setaf 3)
b=$(tput setaf 4)
m=$(tput setaf 5)
c=$(tput setaf 6)
w=$(tput setaf 7)
N=$(tput setaf 8)
R=$(tput setaf 9)
G=$(tput setaf 10)
Y=$(tput setaf 11)
B=$(tput setaf 12)
M=$(tput setaf 13)
C=$(tput setaf 14)
W=$(tput setaf 15)
END=$(tput sgr0)

colorgcc()
    {
    perl -wln -M'Term::ANSIColor' -e '
    m/not found$/ and print "$ENV{N}$`$ENV{END}", "$&", "$ENV{END}"
    or
    m/found$/ and print "$ENV{N}$`${g}", "$&", "$ENV{END}"
    or
    m/yes$/ and print "$ENV{N}$`${g}", "$&", "$ENV{END}"
    or
    m/no$/ and print "$ENV{N}$`$ENV{END}", "$&", "$ENV{END}"
    or
    m/undefined reference to/i and print "$ENV{r}", "$_", "$ENV{END}"
    or
    m/ Error |error:/i and print "$ENV{r}", "$_", "$ENV{END}"
    or
    m/ Warning |warning:/i and print "$ENV{y}", "$_", "$ENV{END}"
    or
    m/nsinstall / and print "$ENV{c}", "$_", "$ENV{END}"
    or
    m/Linking |\.a\b/ and print "$ENV{C}", "$_", "$ENV{END}"
    or
    m/Building|gcc|g\+\+|\bCC\b|\bcc\b/ and print "$ENV{N}", "$_", "$ENV{END}"
    or
    print; '
    }

Upvotes: 0

KillerRabbit
KillerRabbit

Reputation: 173

Well the following is considerably more verbose, but it seems to correctly handle both $FOO and ${FOO} syntax.

#!/usr/bin/env perl

use warnings;
use strict;

my $filename = $ARGV[0];
print(" GIVEN: <$filename>\n");
my $expanded = '';
my @parts = split(/(\$\w+)|(\${\w+})/, $filename);
foreach my $seg (@parts)
  {
    next if (not defined($seg));
    $seg = ($ENV{$1} || '')  if ($seg =~ m/\${?(\w+)}?/);
    $expanded .= $seg;
  }

print("IS NOW: <$expanded>\n");
print(`echo "  ECHO: <$filename>"`);  # How the shell did it.

Here's a sample run...

$ ./expand '$TERM ---${TERM}--- ===${FOO}=== $FOO'
 GIVEN: <$TERM ---${TERM}--- ===${FOO}=== $FOO>
IS NOW: <xterm-color ---xterm-color--- ====== >
  ECHO: <xterm-color ---xterm-color--- ====== >
$

In this version, undefined symbols are replace with an empty string, like the shell. But in my apps I'd rather leave the unexpanded invalid symbol in place making it easier to see what went wrong. Also, if you screw up your bracket matching, the shell will give you a "bad substitution" error, but here we'll just return the string with the broken symbol still in place.

Upvotes: 0

Eugene Yarmash
Eugene Yarmash

Reputation: 149726

If the environmental variables are set, you can use a simple substitution:

$filename =~ s/\$(\w+)/$ENV{$1}/g;

Upvotes: 13

Related Questions