RnC has asked for the wisdom of the Perl Monks concerning the following question:

Hello. I'm trying to creat a "magic GNU cat". It works like this:
Given a file named "myvars" containing:
--BOF--
my name is $USER
my home is at $HOME
--EOF--
then the command should do (e.g):
$ magicat myvars
my name is dudits
my home is at /home/dudits

So far I got here:
--BOF--
#!/usr/bin/perl + $fname = $ARGV[0]; open(FHANDLE, $fname) or die("Error opening file.\n");<br> while(<FHANDLE>) { $_ =~ s/\$([A-Z]+)/\$$1/g; print $_; } close(FHANDLE);
--EOF--
This script prints the variables as it's found in the file, just like GNU cat would do. I need to get the vars "converted" before actually printing it. Any tips or ideas? Thanks in advance.

Replies are listed 'Best First'.
Re: printing enviroment vars from regex
by davorg (Chancellor) on Aug 01, 2004 at 19:24 UTC

    Firstly, the environment variables are accessed via the %ENV hash - so you need to get them from there. Secondly, you've escaped the variable in the replacement string so you'll only get the name of the variable. Remove the escaping to get the value of the variable.

    And a couple of style points - you can make your life easier by using the empty file input operator to save all the hassle of opening and closing files and also there's no need to use the binding operator if you're doing a substitution on $_.

    while(<>) { s/\$([A-Z]+)/$ENV{$1}/g; print $_; }
    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: printing enviroment vars from regex
by Limbic~Region (Chancellor) on Aug 01, 2004 at 19:30 UTC
    RnC,
    This is basic implementation that you can expand as you see fit. It is pretty fragile in the assumptions which means you will have to add your own error handling.
    #!/usr/bin/perl use strict; use warnings; for my $file ( @ARGV ) { if ( ! open(INPUT, '<', $file) ) { warn "Unable to open $file - skipping!\n"; next; } while ( <INPUT> ) { print and next if ! /\$\w+/; $_ =~ s/\$(\w+)/$ENV{$1}/g; print; } }

    Cheers - L~R

       $_ =~ s/\$(\w+)/$ENV{$1}/g
      I'm pretty sure you want:  0 while $_ =~ s/\$(\w+)/$ENV{$1}/;
        BUU,
        Well saying that without an explanation doesn't help me much. Of course it is possible it should be obvious to me why - but I am dense (to be read it is the weekend). It worked fine for my sample input - what advantages does yours have over mine?

        Cheers - L~R

Re: printing enviroment vars from regex
by Aristotle (Chancellor) on Aug 01, 2004 at 19:56 UTC

    With everyone answer your basic question, I want to ask something else. Are you sure you're not writing a templating system here? What exactly are you trying to do in general? There's probably no need for you to do this yourself.

    Makeshifts last the longest.

Re: printing enviroment vars from regex
by CountZero (Bishop) on Aug 01, 2004 at 19:55 UTC
    It's not homework is it?

    No need to use a regex:

    my @output = split(/\n/, `set`); my %environment; foreach (@output) { my ($key, $value)= split /=/; $environment{$key}=$value; } foreach $variable qw/USERNAME HOMEDRIVE/ { ${$variable}=$environment{$variable}; } print "my name is $USERNAME my home is at $HOMEDRIVE";
    Output:
    my name is KJM my home is at C:
    I had to adapt the environment variables a bit as I'm on Windows XP.

    Update: I should have used the %ENV-hash, but TIMTOWTDI!

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

      No, it's not homework. :-) and thanks for the help.