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

I have an application that reads in the lines from a config file that contain UNIX commands, puts the commands in a menu, and runs the command based on the user selection. An example of one of the lines would be something like "echo $user".
# The standard open file, read lines into an array (@lines), close fil +e is completed # Problem $user = $ENV{USER}; foreach $line(@lines) { print "$line\n"; }
The problem is this... When the application is run it outputs 'echo $user' instead of interpolating the value for $user. How would I get the value to be returned? I did implement a workaround by changing '$user' to 'user' in the config file, then running "=~ s/user/$user/g" in the code, and that worked. But I'm sure there's a better way...

Replies are listed 'Best First'.
(tye)Re: Interpolating variables from a file
by tye (Sage) on Sep 19, 2001 at 00:28 UTC

    You can try the fairly powerful and fairly safe: s/([@$]\w[\w\[\]{}']+)/'"'.$1.'"'/gee;

            - tye (but my friends call me "Tye")
(jeffa) Re: Interpolating variables from a file
by jeffa (Bishop) on Sep 19, 2001 at 00:21 UTC
    UPDATE:

    Looks like i didn't read your question well. My original post isn't really a solution to the problem at hand . . .

    What you need is a template! You could actually use HTML::Template for this, or roll your own if it is minor enough. I do recommend delimiting your TAG though, maybe enclose USER in brackets [], or just do what tye says. But you will have to substitute your value in.

    ORIGINAL POST FOLLOWS:


    Oh no! Not the dreaded no strict refs!!

    Seriously, do a Super Search on symbolic references and you will see why that are bad, bad, bad.

    How about an XML solution instead?

    use strict; use XML::Simple; local $/; my $xml = XMLin(<DATA>, forcearray => 1); foreach (@{$xml->{'user'}}) { print "the user is $_\n"; } __DATA__ <users> <user>jeffa</user> <user>foo</user> <user>bar</user> </users>
    If you have XML::Simple installed, you can run this without a hitch. Next step would be to remove the __DATA__ section and place it in your config file. Then you can worry about $ENV{'USER'}. Good Luck!

    jeffa

Re: Interpolating variables from a file
by alien_life_form (Pilgrim) on Sep 19, 2001 at 01:14 UTC
    Is this what you want?
    $u='fool';
    $line='oh you $u'; 
    print $line;
    # outputs => oh you $u
    eval "print qq($line);"
    # outputs => oh you fool
    
    Cheers
    alf
Re: Interpolating variables from a file
by derby (Abbot) on Sep 19, 2001 at 00:50 UTC
    Rich36,

    I'm not quite understanding the flow here. Are you

         1. reading in unix "shell" commands
         2. trying to "fill" the shell variables via perl
         3. execute the input via system, or backticks, or qx
    

    That's pretty wild! I guess there's no changing the config to perl code? Oh well, worth a try. I think you'll need to set your environment and then execute the commands:
    $user = $ENV{USER}; $ENV{user} = $user; # Case sensitivity. Now $user should # be visible to your script snippets foreach $line (@lines) { system( $line ); }
    And of course - all normal danger caveats do apply.

    -derby

      1 and 3. What it's actually being used for is this - In the course of my work, I've got to login to a bunch of different servers under a bunch of different ids - sometimes my own, sometimes an anonymous id. So what this application does is provide a menu of servers to login into - which saves me from having to type a lot or set up/remember a bunch of aliases. After selecting a number, the application calls (with exec()), "rlogin <server_name> -l <user_id>". Here's what the code looks like with the implementation of tye's suggestion (I had to made one minor change in the regex - '@\$' instead of '@$'. With the original one, I was getting '${$user_value}' instead of '{user_value}').
      ####################################################### # Setup variables and packages ####################################################### my $user = $ENV{USER}; my %servernames = (); my $i = 1; ####################################################### # MAIN ####################################################### open(CONFIG, "<lgn.config"); chomp(my @lines = <CONFIG>); close CONFIG; foreach my $line(@lines) { # Add the -l between "server user_name" pattern in $line $line =~ s/\s/ \-l /; # Interpolate the value for "$" values $line =~ s/([@\$]\w[\w\[\]{}']+)/'"'.$1.'"'/gee; $servernames{"$i"} = $line; $i++ } print "***Log in****\n"; print "Select the number of a server and user name combination\n"; foreach my $key(sort{ $a <=> $b }(keys %servernames)) { print "\($key\) $servernames{$key}\n"; } print ": "; chomp(my $ans = <STDIN>); if (($ans eq "") || ($ans =~ m/\D+/g)) { die "Please specify a number\n"; } if (defined($servernames{$ans})) { my $rlogin = "rlogin $servernames{$ans}"; print qq(Executing "$rlogin"\n); exec("$rlogin"); } else { die "Please specify a valid number\n"; }
      The config file (lgn.config) would look like:
      server1 foo server2 $user server2 foo server3 $user
      etc. Thanks to everyone for their help and suggestions....