in reply to Using pattern match

Instead ofthe solution with the sub (which is better than mine ;) you can use eval:

#!/usr/bin/perl -w my %triggers = ( 'You are (\\w+).' => '"Your status is: $1"', ); my $buff = "You are fired!"; foreach my $trigger ( keys ( %triggers ) ) { if ( $buff =~ /$trigger/ ) { #print "Memory contents of \$1: $1\n"; print eval $triggers{$trigger}; } } print "\n";

The evil string eval strips the inner double quotes of the string and interpolates $1.

Replies are listed 'Best First'.
Re^2: Using pattern match
by tceng (Novice) on Aug 10, 2007 at 12:02 UTC
    Thank you all for your help.

    Now I am trying to add another intricacy, that is user input:
    #!/usr/bin/perl -w # builtin triggers my %triggers; # add triggers from params my $trigger_name = shift @ARGV; my $trigger_action_str = shift @ARGV; my $trigger_action = sub { $trigger_action_str }; $triggers{$trigger_name} = $trigger_action; #print "$trigger_name -> $trigger_action_str\n"; my $buff = "You are fired!"; foreach my $trigger ( keys ( %triggers ) ) { if ( $buff =~ /$trigger/ ) { #print "Memory contents of \$1: $1\n"; print &{$triggers{$trigger}}; } } print "\n";
    If I try to run this:
    perl triggers2.pl "You are (\w+)." "You are: $1"
    it doesn't work.
    Any advice, please? Would the eval solution work with this?
    Cheers,

    tceng
      The shell is eating $1. Escape the dollar: \$1 or use single quotes on the command line.

        Hm,

        actually what I get is:
        You are: $1
        If I escape the dollar sign, I get:
        You are: \$1
        I am using Windows here, but I was asking myself if it will work when I read from file, for it's what I really need with the script.
        I'll have a go at it.
        Thanks!

        tceng
      Yes, you will definitely need string eval here.

      Something like this:

      #!/usr/bin/perl -w use strict; # builtin triggers my %triggers; # add triggers from params my $trigger_name = shift @ARGV; my $trigger_action_str = shift @ARGV; $triggers{$trigger_name} = $trigger_action_str; my $buff = "You are fired!"; foreach my $trigger ( keys ( %triggers ) ) { if ( $buff =~ /$trigger/ ) { print eval '"' . $triggers{$trigger} . '\n"'; } }

      But this is not a design anyone will recommend.

      Besides, this will not run in taint mode.

        Thanks akho. I ended up with this, can you please advise?
        #!/usr/bin/perl -w use strict; # builtin triggers my %triggers; # add triggers from params my $trigger_name = shift @ARGV; my $trigger_action_str = shift @ARGV; $triggers{$trigger_name} = sub { eval $trigger_action_str; }; my $buff = "You are fired!"; foreach my $trigger ( keys ( %triggers ) ) { if ( $buff =~ /$trigger/ ) { print &{$triggers{$trigger}}; } }
        If I try:
        perl triggers2.pl "You are (\w+)." "\"You are: $1\""
        I get:
        You are: fired

        Correct. You see, I just have to add escaped quotes on the command line. But is this one a good way to go, pls?

        Cheers,

        tceng
      the eval() solution would work in the above case, but be advised that this approach is even eviler than (string) eval() used on its own. this is because code can be evaluated at run time both in eval() and in the extended regex pattern (?{{ code... }}).

      see the subject of taint checking and perlsec for more horrific details.

        Thanks for your feedback, it's very interesting and appreciated.
        The script will run as server and therefore I'd like it to tun in tainted mode, so I figured out another way to do things:
        #!/usr/bin/perl -w -T use strict; # builtin triggers my %triggers; # add triggers from params my $trigger_name = shift @ARGV; my $trigger_action_str = shift @ARGV; $triggers{$trigger_name} = $trigger_action_str; my $buff = "You are fired!"; foreach my $trigger ( keys ( %triggers ) ) { if ( $buff =~ /$trigger/ ) { my $c1 = $1; my $txt = $triggers{$trigger}; $txt =~ s/\$1/$c1/g; print $txt; } }
        Yes, that's not elegant for I should save each memory container $1, $2, and so on to be general enough, but at least I can run it in tainted mode:
        perl -T triggers4.pl "You are (\w+)." "Your status: $1"

        So I get:
        Your status: fired

        Cheers,
        tceng