1

Here is an example of what i'm trying to do: I want to "defined" a name for the input and then when it's taken into a function, only then it will substitute all the 3 variables.

$place_holder = 'f${file_case}_lalal_${subcase}_${test}';

.... somewhere else in another function:

read file containing 3 set of numbers on each line that represents the $file_case, $subcase, $test

while(<IN>){
   ($file_case, $subcase, $tset) = split;
   $input = $place_holder    #### line #3 here needs to fix
   print " $input \n";
}

Unfortunately, it prints out f${file_case}lalal${subcase}_${test} for every single line. I want those variables to be substituted. How do I do that, how do I change line #3 to be able to output as i wanted ? I don't want to defined the input name in the subroutine, it has to be in the main.

2
  • 1
    Note: interpolation only happens in double-quoted strings, but your example is single-quoted. Commented Feb 4, 2017 at 17:38
  • I know. the $place_holder acts like a function at that time, the 3 variables are NOT known yet. therefore NOT to be substituted. But the $place_holder needs to be in a place where user can easily change to what they like. The rest of the substitution are hidden in functions where user do not need to change. Commented Feb 4, 2017 at 21:23

4 Answers 4

3

You can do it using subroutines for example, if that satisfies your criteria

use warnings;
use strict;

my $place_holder = sub {
    my ($file_case, $subcase, $test) = @_;    
    return "f${file_case}_lalal_${subcase}_${test}";
}

# ...

while (<IN>) { 
    my ($file_case, $subcase, $tset) = split;
    #
    #  Code to validate input
    #
    my $input = $place_holder->($file_case, $subcase, $tset);
    print "$input\n";
}

I've used code reference with an anonymous subroutine in anticipation of uses that may benefit from it, but for the specified task alone you can use a normal subroutine as well.

Note that you have $test and $tset, which doesn't affect the above but may be typos.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you. That certainly is one way to make it work elegantly.
@OngBengSeong Thank you -- the points I had in mind are that it separates phases of processing for easier management (for example, precise variable names don't matter), the coderef can be passed around as needed -- and it avoids eval-ing user input.
what if I have 12 different set of filenames and i go with subroutine style my $file_name = sub{ }
@OngBengSeong You mean this whole thing processes a file and it needs to be done for 12 different files? You just put it all in a loop over those filenames. So for each filename the my $place_holder = sub { ... }; is defined, (then you open the file), then you read from it doing what is in while (<IN>). If it is something more involved it may be a good separate question
Hi Zdim, you'll be happy to know I know end up using a subroutine for the name like your suggestion. I've actually tried both and after a few days, change to the subroutine version which I think is still more elegant and organized. Thank you again !!
2

You may use the String::Interpolate module, like this

use String::Interpolate 'interpolate';

my $place_holder = 'f${file_case}_lalal_${subcase}_${test}';


while ( <IN> ) {
    my ($file_case, $subcase, $test) = split;

    my $input = interpolate($place_holder);
    print "$input\n";
}

The module gives access to Perl's built-in C code that performs double-quote interpolation, so it is generally fast and accurate

Comments

0

A while after I posted, I found a way to do it.

in the ## line 3, do this:

($input = $place_holder) =~ s/(\${w+})/$1/eeg;

and everything works. Yes the above tset is a typo, meant to be test. Thank for everybody's response.

3 Comments

This is what I warned about initially -- it evaluates user input. That is inherently dangerous. I don't mean only for possible bad intent, but mere typos or wrong data can get evaluated so to wreak havoc on your code. Note that this eval-uates content of $1 as arbitrary Perl code. (Which is why I didn't mention it in my answer, despite referring to it in an early comment.) I strongly suggest not doing this, if there is another way.
By "user input" in my previous comment, I meant also input from data. We never can be sure what is in a "data" file. I would add a comment that data would need to be verified extensively before /ee, which involves eval.
It is good that you found a working solution yourself and posted it (btw, I didn't downvote it).
-1

Try eval while(<IN>){ ($file_case, $subcase, $tset) = split; $input = eval $place_holder #### line #3 here needs to fix print " $input \n"; }

2 Comments

Unfortunately I've tried that before and it doesn't work. Thank you.
what error you got? If you didn't pick it, it's same as your solution. So it should work.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.