tags:

views:

151

answers:

3

I'm trying to make an on-the-fly pattern tester in Perl. Basically it asks you to enter the pattern, and then gives you a >>>> prompt where you enter possible matches. If it matches it says "%%%% before matched part after match" and if not it says "%%%! string that didn't match". It's trivial to do like this:

while(<>){
    chomp;
    if(/$pattern/){
        ...
    } else {
        ...
    }
}

but I want to be able to enter the pattern like /sometext/i rather than just sometext I think I'd use an eval block for this? How would I do such a thing?

A: 

This works for me:

my $foo = "My bonnie lies over the ocean";

print "Enter a pattern:\n";
while (<STDIN>) {
   my $pattern = $_;
   if (not ($pattern =~ /^\/.*\/[a-z]?$/)) {
      print "Invalid pattern\n";
   } else {
      my $x = eval "if (\$foo =~ $pattern) { return 1; } else { return 0; }";
      if ($x == 1) {
         print "Pattern match\n";
      } else {
         print "Not a pattern match\n";
      }
   }
   print "Enter a pattern:\n"
}
Josh K
+1  A: 

You can write /(?i:<pattern>)/ instead of /<pattern>/i.

jrockway
+1  A: 

This sounds like a job for string eval, just remember not to eval untrusted strings.

#!/usr/bin/perl

use strict;
use warnings;

my $regex = <>;
$regex = eval "qr$regex" or die $@;
while (<>) {
    print  /$regex/ ? "matched" : "didn't match", "\n";
}

Here is an example run:

perl x.pl
/foo/i
foo
matched
Foo
matched
bar
didn't match
^C
Chas. Owens
How would this work with a substitution instead of a match?
misterMatt
You mean if the user passes in the string "s/foo/bar/"? In that case I would say something like `my $subst = <>; while (<>) { eval $subst or die $@; print }`, but again, this is __very__ dangerous. Whatever the user passes in on the first line will be executed as Perl code.
Chas. Owens
I did try something similar - but the patter in the substitution kept failing to match anything.
misterMatt