Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

variable interpretation while reading from a file

by amma (Novice)
on Nov 29, 2013 at 09:56 UTC ( #1064933=perlquestion: print w/replies, xml ) Need Help??
amma has asked for the wisdom of the Perl Monks concerning the following question:

$name = guest; $id = 1; open(SOURCE, "<file1.txt"); open(SINK, ">file2.txt"); while (<SOURCE>) { #open(DATA,"<pattern.txt"); while ( <DATA> ) { print SINK "$_" if /startpattern/ .. /Endpattern/; } } __DATA__ #start pattern my name is $name blahhhhhhh my id is $id blahhhh #Endpattern

The variables are not interpreted while writing to the SINK file. What I am missing here? How to interpret the variables.

Replies are listed 'Best First'.
Re: variable interpretation while reading from a file
by boftx (Deacon) on Nov 29, 2013 at 10:09 UTC

    I think you would need to do an eval of some type on $_ to make that happen, and that is BAD NEWS(tm)! You'll probably need to do some sort of regex substitution instead to keep it relatively safe.

    It helps to remember that the primary goal is to drain the swamp even when you are hip-deep in alligators.

      Regex method worked, thanks

Re: variable interpretation while reading from a file
by Anonymous Monk on Nov 29, 2013 at 10:37 UTC
Re: variable interpretation while reading from a file
by ww (Bishop) on Nov 29, 2013 at 14:23 UTC
    semi-OT, but since the Seeker says regexen solved the problem, I suspect a typo in the OP:

    /startpattern/ (Ln 9) is NOT the same as /start pattern/ (in #start pattern in Ln 14.

    Further, while others have mentioned the explanation for non-interpolation, no-one, OP included, has posted a solution -- so here's one (which omits the -- confusing to me -- script's use of both a file (of unspecified content) and __DATA__:

    Data file:
    #start pattern my name is $name blahhhhhhh my id is $id blahhhh #Endpattern #newpattern my name is $name blash my id is $id #endofpattern #startpattern my name is $name blaghhh my id is $id #endpattern #start pattern my name is fred blahhhhhhh my id is 42 blahhhh #Endpattern #1064933.txt
    #!/usr/bin/perl use 5.016; use warnings; # 1064933 my $name="guest"; my $id = 1; $/ = "\n\n"; open(SOURCE, "<1064933.txt") or die "Can't open 1064933.txt, $!"; open(SINK, ">1064933OUT.txt") or die "Can't open 1064933OUT.txt, $!"; while (<SOURCE>) { if ( /start pattern/ .. /Endpattern/) { s/\$name/$name/; s/\$id/$id/; print SINK $_; next; } }
    D:\_Perl_\PMonks>cat 1064933OUT.txt #start pattern my name is guest blahhhhhhh my id is 1 blahhhh #Endpattern #start pattern my name is fred blahhhhhhh my id is 42 blahhhh #Endpattern

    Note, however, that while this limits the exploitability of using an eval solution (by restricting the substitutions to the programmer's specs), it's far short of production-worthy. But then, the notion of globally replacing \$name with "guest" and making all \$id evaluate to 1 suggests that the example code has little resemblence to the actual task at hand.

      What is next doing there? Also, /g might be needed if variables can be repeated on lines; and it gets very tricky if a variable's name is a part of other variable's name:
      my car is $car_colour $car
      لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

        Aaaarghhhhh. Good catch! Thank you.

        next is a left-over (forgetfully 'unremoved') from an alternate approach which was later abandoned.

        As to the possibility of multiple variables with similar name_parts -- all on a single line: that's not something I considered, as it appears to be outside the OP's spec. Oversight aside, however, that does indeed make the coding a little tricky...
              ... perhaps something like this [added to prev code and, yes, with the next removed :-)]:

        say "\tDone with source and sink files\n"; $/ = "\n"; # restore record separator my @choroba = ('choroba my car -- a $car -- is $car_colour. Choroba-', 'choroba my car2 is $car_colour $car. Choroba-', 'choroba my car3 is $car_colour $car Choroba-', 'choroba my car4 is $car_colour and |secondinstance: $ca +r_colour| |firstinstance:$car| Choroba-', ); for (@choroba) { if ( $_ =~ /choroba/ .. /Choroba-/ ) { s/choroba/ /; # ... s/Choroba-/ /; # or set record separator s/\$car_colour/red/g; # yup, need the g s/\$car[^_]{1}/ford/; say $_; } }
        which produces terminal output:
        Done with source and sink files my car -- a ford-- is red. my car2 is red ford my car3 is red ford my car4 is red and |secondinstance: red| |firstinstance:ford


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1064933]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (15)
As of 2017-02-23 14:11 GMT
Find Nodes?
    Voting Booth?
    Before electricity was invented, what was the Electric Eel called?

    Results (347 votes). Check out past polls.