5 Stimmen

Wie kann ich bei einer Such- und Ersetzungsfunktion mit Perl Text anhängen statt ersetzen?

Ich versuche, Suchen und Ersetzen mit einer Regex in Perl zu tun.

Der Text, den ich suche, lautet:

<space>Number<space>NumberNumberNumber

und ich möchte sie ersetzen durch:

<space>Number<space>NumberNumberNumberI

Ich habe die folgende Regex, die bei der Suche nach der Zeichenfolge funktioniert:

\s[0-9]\s[0-9[0-9][0-9] 

Aber was mache ich, wenn ich die Zeichenfolge ersetzen will? Im Grunde möchte ich nur ein "I" an das Ende anhängen.

Ich benutze:

perl -pi -e "s/\s[0-9]\s[0-9][0-9][0-9]/I/;" testFile 

aber hier wird das Ganze durch I ersetzt, anstatt es anzuhängen.

9voto

Chas. Owens Punkte 62716

Dafür sind Rückverweise gedacht. Umgeben Sie einfach den Textabschnitt, den Sie erfassen möchten, mit Klammern. Der erste Satz Klammern ist in $1 verfügbar, der zweite in $2 und so weiter.

s/(\s[0-9]\s[0-9]{3})/$1I/

Mit Perl 5.10 haben wir benannte Erfassungen so kann man sagen

s/(?<bodytext>\s[0-9]\s[0-9]{3})/$+{bodytext}I/

Das Zeug dazwischen < y > ist der Name. Namen werden zu Schlüsseln in der %+ Variable und die Werte sind der erfasste Text.

Eine andere Lösung ist die Verwendung eines positive Look-Behinds mit Null-Breite

s/(?<=\s[0-9]\s[0-9]{3})/I/

oder seine, in Perl 5.10 neue, Kurzform \K

s/\s[0-9]\s[0-9]{3}\K/I/

Versuchen Sie

perl -pi -e 's/(\s[0-9]\s[0-9][0-9][0-9])/$1I/' filename

Wenn Sie doppelte Anführungszeichen verwenden, wird der $1 von der Shell interpoliert, bevor Perl ihn überhaupt sieht. Wenn Sie Probleme mit etwas haben, von dem Sie denken, dass es funktionieren sollte, kann es eine gute Idee sein, einen Blick darauf zu werfen, was Perl sieht. Sie können dies mit B::Abreise :

perl -MO=Deparse -pi -e "s/(\s[0-9]\s[0-9][0-9][0-9])/$1I/" filename

Dies führt zu der folgenden Ausgabe.

BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/(\s[0-9]\s[0-9][0-9][0-9])/I/;
}
continue {
    print $_;
}
-e syntax OK

Daraus ergibt sich, dass $1 fehlt. Versuchen wir es noch einmal mit einfachen Anführungszeichen:

perl -MO=Deparse -pi -e 's/(\s[0-9]\s[0-9][0-9][0-9])/$1I/' filename
BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/(\s[0-9]\s[0-9][0-9][0-9])/$1I/;
}
continue {
    print $_;
}
-e syntax OK

Und einmal mit der Flucht:

perl -MO=Deparse -pi -e "s/(\s[0-9]\s[0-9][0-9][0-9])/\$1I/" filename
BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/(\s[0-9]\s[0-9][0-9][0-9])/$1I/;
}
continue {
    print $_;
}
-e syntax OK

1voto

cnst Punkte 23716

Eine kürzere Version der Antwort aus dem Jahr 2009 - Sie können verwenden positive Rückschaubehauptung mit der Breite Null , (?<=pattern) o \K , um etwas nach dem Spiel einzufügen:

%echo "test" | perl -p -e "s/(?<=test)/ing/"
testing
%echo "test" | perl -p -e "s/test\K/ing/"
testing
%

Um etwas vor dem Spiel einzufügen, können Sie alternativ positive Vorausschau-Behauptung mit Null-Breite , (?=pattern) :

%echo "test" | perl -p -e "s/(?=test)/#/"
#test
%

Referenz:

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