Wie kann ich die Variableninterpolation mit dem Perl-Substitutionsoperator deaktivieren?

StackOverflow https://stackoverflow.com//questions/12678519

  •  12-12-2019
  •  | 
  •  

Frage

Ich versuche, eine bestimmte Zeile in einer Textdatei auf VMS zu ersetzen.Normalerweise ist dies ein einfacher Einzeiler mit Perl.Allerdings stieß ich auf ein Problem, als die Ersatzseite ein Symbol war, das einen VMS-Pfad enthielt.Hier ist die Datei und was ich versucht habe:

Inhalt von file1.txt:

foo
bar
baz
quux

Versuch, die 3. Zeile zu ersetzen:

$ mysub = "disk$data1:[path.to]file.txt"
$ perl -pe "s/baz/''mysub'/" file1.txt

Ergibt die folgende Ausgabe:

foo
bar
disk:[path.to]file.txt
quux

Es sieht so aus, als ob Perl übereifrig war und das ersetzt hat $data1 Teil des Pfades mit dem Inhalt einer nicht existierenden Variablen (d. h. nichts).Das Ausführen mit dem Debugger hat dies bestätigt.Ich habe nicht geliefert /e, also dachte ich, Perl sollte den Text einfach so ersetzen, wie er ist.Gibt es eine Möglichkeit, Perl dazu zu bringen, das zu tun?

(Beachten Sie auch, dass ich ein ähnliches Verhalten in der Linux-Befehlszeile reproduzieren kann.)

War es hilfreich?

Lösung

Mit genau der richtigen Mischung aus Anführungszeichen und doppelten Anführungszeichen erreichen Sie Folgendes:

Wir erstellen eine enge Verkettung von „string“ + „Ersatzsymbol“ + „string“.Die beiden Zeichenfolgen in doppelten Anführungszeichen enthalten einfache Anführungszeichen für den Ersatz.Gekünstelt...Aber es funktioniert.

$ perl -pe "s'baz'"'mysub'"'" file1.txt

Das ist eine Lösung auf DCL-Ebene.

Verwenden Sie für eine Perl-Lösung die q() Operator für eine nicht interpolierte Zeichenfolge und führen Sie diese aus.Fügen Sie das Symbol mithilfe einer einfachen DCL-Ersetzung in die Klammern ein.Das ist mein Favorit, weil es für mich (fast) Sinn ergibt und mit Zitaten nicht zu sehr verwirrend wirkt.

$ perl -pe "s/baz/q(''mysub')/e" file1.txt

Andere Tipps

Als Ruakh Beim Lesen meines Kommentars habe ich festgestellt, dass das Problem der Perl-Interpolation durch Zugriff auf gelöst werden kann %ENV Hash, anstatt eine Shell-Variable zu verwenden:

perl -pwe "s/baz/$ENV{mysub}/" file1.txt

Hinzugefügt -w weil ich nicht daran glaube, es nicht zu benutzen warnings sogar in Einzeilern.

Ich habe seit Jahrzehnten nicht einmal ein VMS-System gesehen, aber ...deinem Siegel entkommen?

$ mysub = "disk\$data1:[path.to]file.txt"

oder vielleicht

$ mysub = "disk\\$data1:[path.to]file.txt"

?

Für sh oder ein Derivat, das ich verwenden würde

perl -pe'BEGIN { $r = shift(@ARGV) } s/baz/$r/' "$mysub" file1.txt

Ansonsten muss man den Wert irgendwie verheimlichen mysub in ein Perl-String-Literal umwandeln.Das wäre komplizierter.Finden Sie das Äquivalent für Ihre Shell.

Bearbeiten durch OP:

Ja, das funktioniert.Das VMS-Äquivalent ist

perl -pe "BEGIN { $r = shift(@ARGV) } s/baz/$r/" 'mysub' file1.txt

Du musst dem entkommen $ mit \$.Andernfalls erkennt Perl eine Variablenreferenz und ersetzt die Zeichenfolge $data1 mit dem Inhalt von $data1 bevor der reguläre Ausdruck ausgewertet wird.Wie du es nicht definiert hast $data1 es ist natürlich leer.

Sie können den folgenden Code verwenden:

$ mysub='disk\$data1:[path.to]file.txt'
$ perl -pe 's/baz/'$mysub'/' FILE
foo
bar
disk$data1:[path.to]file.txt
quux

Sie könnten versuchen, einen logischen Namen anstelle eines DCL-Symbols zu verwenden:

$ define mysub "disk$data1:[path.to]file.txt"
$ $ perl -pe "s/baz/mysub/" file1.txt

Verwenden Sie sed.

Sed wird nicht versuchen zu interpolieren $data1 als Variable, also sollten Sie bekommen, was Sie wollen.

$ sed -e "s/baz/''mysub'/" file1.txt
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top