Perl qr // and lookup

I am writing a tiny program that takes user input using Getops, and based on it, the program will either try to match the template with some text, or replace the text for what matches.

The problem I am facing is that I cannot get the replacement part to work. I am looking at the qr // entry on the man pages: http://perldoc.perl.org/perlop.html#Regexp-Quote-Like-Operators , but I'm out of luck. In this case, I tried to simulate my code in the same way as the documents. I compile the match pattern and replace it with wildcard.

Can someone please indicate where I am going wrong? (Don't worry too much about security, this is just a little script for personal use)

Here is what I look at:

if($options{r}){ my $pattern = $options{r}; print "\nEnter Replacement text: "; my $rep_text = <STDIN>; #variable grab, add flags to pattern if they exist. $pattern .= 'g' if $options{g}; $pattern .= 'i' if $options{i}; $pattern .= 's' if $options{s}; #compile that stuff my $compd_pattern = qr"$pattern" or die $@ ; print $compd_pattern; #debugging print "Please enter the text you wish to run the pattern on: "; my $text = <STDIN>; chomp $text; #do work and display if($text =~ s/$compd_pattern/$rep_text/){ #if the text matched or whatever print $text; } else{ print "$compd_pattern on \n\t{$text} Failed. "; } } #end R FLAG 

When I run it with -r "/ matt /" -i and type the replacement text 'matthew', it fails on the text 'matt'. Why is this?

EDIT:

Thanks for the responses guys! It was very helpful. I combined both of your suggestions into a working solution to the problem. I have to handle the / g flag a little differently. Here is a working example:

 if($options{r}){ my $pattern = $options{r}; print "\nEnter Replacement text: "; my $rep_text = <STDIN>; chomp $rep_text; #variable grab, add flags to pattern if they exist. my $pattern_flags .= 'i' if $options{i}; $pattern_flags .= 's' if $options{s}; print "Please enter the text you wish to run the pattern on: "; my $text = <STDIN>; chomp $text; #do work and display if($options{g}){ if($text =~ s/(?$pattern_flags:$pattern)/$rep_text/g){ #if the text matched or whatever (with the g flag) print $text; } else{ print "$pattern on \n\t{$text} Failed. "; } } else{ if($text =~ s/(?$pattern_flags:$pattern)/$rep_text/){ #if the text matched or whatever print $text; } else{ print "$pattern on \n\t{$text} Failed. "; } } } #end R FLAG 
+6
regex perl substitution
source share
2 answers

As chaos points out, you will run into some difficulties using qr// . Do you really need to pre-compose the template? If not, this strategy may work:

 my $pattern = 'matt'; my $text = 'Matt'; my $rep_text = 'Matthew'; my $pattern_opts = 'i'; print $text, "\n" if $text =~ s/(?$pattern_opts:$pattern)/$rep_text/; 

Update in response to your new code : you can use this approach:

 my ($orig, $patt, $rep, $flags) = qw(FooFooFoo foo bar ig); my $make_replacement = $flags =~ s/g// ? sub { $_[0] =~ s/(?$flags:$patt)/$rep/g } : sub { $_[0] =~ s/(?$flags:$patt)/$rep/ } ; if ( $make_replacement->($orig) ){ print $orig; } else { print "Failed..."; } 
+11
source share

Run it with -r "matt" and not -r "/matt/" . You do not need and, in fact, cannot, specify pattern delimiters in your options string. Quotation marks are delimiters in qr . This way he is really looking for matt with slashes around it, the way you run it, which you don't want. You are trying to use quotation marks to tell Perl to treat your template string as it was in the source code, but unfortunately you cannot do this.

All these templates that you added for other parameters will also not work. You will need to change the way regular expression is compiled if you want to do all this. Something like this can do this for /i and /s :

 my $compd_pattern = qr/$pattern/ or die $@ ; $compd_pattern = qr/$compd_pattern/i if $options{i}; $compd_pattern = qr/$compd_pattern/s if $options{s}; 

For /g you will need support for an alternative search / replace version. /g not a valid modifier for qr// .

+7
source share

All Articles