6 Stimmen

Perl qr// und Ersetzung

Ich schreibe ein winziges Programm, das Benutzereingaben mit Getops entgegennimmt und darauf basierend entweder versucht, ein Muster mit einem Text abzugleichen oder den übereinstimmenden Text zu ersetzen.

Das Problem, das ich habe, ist, dass ich den Teil mit der Substitution nicht zum Laufen bringe. Ich schaue mir den qr//-Eintrag in den Man Pages 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 Docs in diesem Fall zu modellieren. Ich kompiliere ein Match-Pattern und ersetze dieses durch eine Substitution.

Kann mir jemand sagen, wo ich falsch liege? (Machen Sie sich keine allzu großen Sorgen um die Sicherheit, dies ist nur ein kleines Skript für den persönlichen Gebrauch)

Hier ist, was ich sehe:

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

Wenn ich es mit -r "/matt/" -i ausführe und den Ersatztext "matthew" für den Text "matt" eingebe, schlägt es fehl. Woran liegt das?

EDITAR:

Danke für die Antworten, Jungs! Das war wirklich sehr hilfreich. Ich habe eure beiden Vorschläge zu einer funktionierenden Lösung für das Problem kombiniert. Ich muss das /g-Flag ein wenig anders behandeln. Hier ist das funktionierende Beispiel:

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

10voto

FMc Punkte 40706

Als chaos weist darauf hin werden Sie auf einige Schwierigkeiten stoßen, wenn Sie qr// . Müssen Sie das Muster wirklich vorkompilieren? Wenn nicht, könnte eine Strategie wie diese funktionieren:

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/;

Aktualisierung als Antwort auf Ihren neuen Code : Sie könnten einen Ansatz wie diesen in Betracht ziehen:

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

6voto

chaos Punkte 118918

Führen Sie es mit -r "matt" , nicht -r "/matt/" . Sie müssen und können in Ihrer Optionszeichenfolge keine Musterbegrenzer angeben. Die Anführungszeichen sind die Begrenzungszeichen in Ihrem qr . Es sucht also tatsächlich nach matt mit Schrägstrichen drumherum, so wie Sie es ausführen, was nicht das ist, was Sie wollen. Sie versuchen, die Anführungszeichen zu verwenden, um Perl zu sagen, dass es Ihre Musterzeichenfolge wie Quellcode behandeln soll, aber leider können Sie das nicht.

All die Musteranhänge, die Sie für die anderen Optionen verwenden, werden ebenfalls nicht funktionieren. Sie müssen die Art und Weise ändern, wie Sie die Regex kompilieren, wenn Sie all das tun wollen. Etwas wie dies könnte es tun für /i y /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};

Für /g müssen Sie eine alternative Version des Suchens/Ersetzens unterstützen. /g ist kein gültiger Modifikator für qr// .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X