Re: Using pattern match
by akho (Hermit) on Aug 10, 2007 at 11:09 UTC
|
$1 doesn't have a value when you define %triggers. You can postpone the evaluation of your string using a sub:
#!/usr/bin/perl -w
use strict;
my %triggers =
(
'You are (\\w+).' => sub { "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 &{$triggers{$trigger}};
}
}
print "\n";
| [reply] [d/l] [select] |
|
Thank you very much, akho. It works perfectly now.
Cheers,
tceng
| [reply] |
Re: Using pattern match
by moritz (Cardinal) on Aug 10, 2007 at 11:43 UTC
|
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.
| [reply] [d/l] |
|
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 | [reply] [d/l] [select] |
|
The shell is eating $1. Escape the dollar: \$1 or use single quotes on the command line.
| [reply] [d/l] [select] |
|
|
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. | [reply] [d/l] [select] |
|
|
|
| [reply] [d/l] [select] |
|
Re: Using pattern match
by Moron (Curate) on Aug 10, 2007 at 11:34 UTC
|
There is also the fact that single quotes produce literally what is there rather than translating $variables. The example with sub has used double quotes whereas the OP didn't. So instead of using sub, it so happens you could also achieve the delay by keeping the single quotes and putting an eval around what is being printed and of course it makes me wonder if the OP code originated in or was copied from that kind of example somewhere.
__________________________________________________________________________________
^M Free your mind! | [reply] |
|
Darn. It seems like every time there's an issue I can actually speak with some authority (quotes and variable interpolation), somebody has beaten me to the punch and has a better answer.
Guess I'll just keep learnin' until I can answer the less easy stuff :).
| [reply] |
Re: Using pattern match
by Anonymous Monk on Aug 10, 2007 at 18:04 UTC
|
May be I am missing something obvious, but wouldn't a simple printf work ? (assuming there is only one variable needed).
Something like that :
#!/usr/bin/perl -w
my %triggers =
(
'You are (\\w+).' => 'Your status is: %s',
);
my $buff = "You are fired!";
foreach my $trigger ( keys ( %triggers ) )
{
if ( $buff =~ /$trigger/ )
{
print sprintf( $triggers{$trigger}, $1);
}
}
print "\n";
| [reply] [d/l] |
|
s/print sprintf/printf/
| [reply] [d/l] |
|
Thank you for your contribute!
Unfortunately the idea was to be able to process regular expressions with more than one matching patter and be able to print out something that involves those matching patterns.
I think it would help if Perl generates a list whose elements are all the matching patterns in a s/// operation. Ie that list contains $1, $2, $3, and so on, and a foreach can be done on it, so that one can pick up all the defined variables in one go and then substitute them with the method I showed before (s/\$1/$1/g). Is there one such list, please?
Cheers,
tceng
| [reply] |
|
|