2009-08-03 18 views
6

Ich schreibe ein kleines Programm, das Benutzereingaben mit Getops nimmt, und basierend darauf wird das Programm entweder versuchen, ein Muster mit etwas Text zu vergleichen, oder ersetzen Sie Text für was übereinstimmte.Perl qr // und Substitution

Das Problem, das ich habe, ist, dass ich den Substitutionsteil nicht funktionieren kann. Ich schaue mir den qr // Eintrag in den man-Seiten an: http://perldoc.perl.org/perlop.html#Regexp-Quote-Like-Operators, aber ich habe kein Glück damit. Ich habe versucht, meinen Code genau wie die Dokumente in diesem Fall zu modellieren. Ich kompiliere ein Übereinstimmungsmuster und ersetze das in eine Substitution.

Könnte jemand darauf hinweisen, wo ich falsch liege? (Keine Sorge um die Sicherheit zu viel, das ist nur ein kleines Skript für den persönlichen Gebrauch)

Hier ist, was bei Ich suche nach:

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 [email protected]; 
    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 

Wenn ich es mit -r laufen „/ matt/"-i, und geben Sie den Ersetzungstext" matthew "ein, auf dem Text" matt ", es schlägt fehl. Warum ist das?

EDIT:

Danke für die Antworten Jungs! Das war wirklich sehr hilfreich. Ich habe beide Vorschläge zu einer funktionierenden Lösung für das Problem kombiniert. Ich muss die/g Flagge etwas anders handhaben. Hier ist die Arbeitsprobe:

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 

Antwort

11

Wie Chaos zeigt, werden Sie einige Schwierigkeiten mit qr// auftreten. Müssen Sie das Muster wirklich vorkompilieren? Wenn nicht, könnte eine Strategie, wie diese Arbeit:

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 Reaktion auf den neuen Code: Sie betrachten könnte einen Ansatz wie folgt aus:

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..."; 
} 
+0

Ahh, sehr gut mit der '(? opt: pat) '. Ich vergesse immer, dass du das kannst. – chaos

7

Run mit -r "matt", nicht -r "/matt/". Sie müssen keine Mustertrennzeichen in der Optionszeichenfolge angeben und können dies auch nicht tun. Die Anführungszeichen sind die Trennzeichen in Ihrem qr. Es sucht also nach matt mit Schrägstrichen, so wie Sie es ausführen, was nicht das ist, was Sie wollen. Sie versuchen, die Anführungszeichen zu verwenden, um Perl anzuweisen, Ihre Musterzeichenfolge wie Quellcode zu behandeln, aber das können Sie leider nicht tun.

Alle diese Musteranhänge, die Sie für die anderen Optionen tun, werden auch nicht funktionieren. Sie müssen die Art ändern, wie Sie die Regex kompilieren, wenn Sie das alles tun wollen. So etwas wie dies tun könnte es für /i und /s:

my $compd_pattern = qr/$pattern/ or die [email protected]; 
$compd_pattern = qr/$compd_pattern/i if $options{i}; 
$compd_pattern = qr/$compd_pattern/s if $options{s}; 

Für /g Sie eine alternative Version der Suche unterstützen müssen/ersetzen. /g ist kein gültiger Modifikator für qr//.