Comment puis-je désactiver l'interpolation de variables avec l'opérateur de substitution Perl ?

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

  •  12-12-2019
  •  | 
  •  

Question

J'essaie de remplacer une ligne particulière dans un fichier texte sur VMS.Normalement, il s'agit d'un simple one-liner avec Perl.Mais j'ai rencontré un problème lorsque le côté de remplacement était un symbole contenant un chemin VMS.Voici le fichier et ce que j'ai essayé :

Contenu du fichier1.txt :

foo
bar
baz
quux

Tentative de remplacement de la 3ème ligne :

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

Donne le résultat suivant :

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

Il semble que Perl ait été trop enthousiaste et ait remplacé le $data1 partie du chemin avec le contenu d'une variable inexistante (c'est-à-dire rien).L'exécution avec le débogueur l'a confirmé.je n'ai pas fourni /e, j'ai donc pensé que Perl devrait simplement remplacer le texte tel quel.Existe-t-il un moyen pour que Perl fasse cela ?

(Notez également que je peux reproduire un comportement similaire sur la ligne de commande Linux.)

Était-ce utile?

La solution

Avec juste la bonne combinaison de guillemets et de guillemets doubles, vous pouvez y arriver :

Nous créons une concaténation étroite de « chaîne » + « symbole de remplacement » + « chaîne ».Les deux chaînes entre guillemets doubles contiennent des guillemets simples pour le substitut.Artificiel...mais ça marche.

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

C'est une solution de niveau DCL.

Pour une solution Perl, utilisez le q() opérateur pour une chaîne non interpolée et exécutez-le.Insérez le symbole dans les parenthèses en utilisant une simple substitution DCL.C'est mon préféré car cela a (presque) du sens pour moi et ne devient pas trop déroutant avec les citations.

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

Autres conseils

Comme ruakh découvert en lisant mon commentaire, le problème de l'interpolation Perl peut être résolu en accédant au %ENV hachage, plutôt que d'utiliser une variable shell :

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

Ajoutée -w parce que je ne crois pas qu'il faille ne pas utiliser warnings même en one-liners.

Je n'ai même pas vu de système VMS depuis des décennies, mais...échapper à ton sceau ?

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

ou peut-être

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

?

Pour sh ou un dérivé, j'utiliserais

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

Sinon, vous devez d'une manière ou d'une autre dissimuler la valeur de mysub en une chaîne Perl littérale.Ce serait plus compliqué.Trouvez l'équivalent pour votre shell.

Modifier par OP :

Oui, cela fonctionne.L'équivalent VMS est

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

Il faut échapper au $ avec \$.Sinon, Perl voit une référence à une variable et remplace la chaîne $data1 avec le contenu de $data1 avant que l'expression régulière soit évaluée.Comme tu ne l'as pas défini $data1 il est bien sûr vide.

Vous pouvez utiliser le code suivant :

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

Vous pouvez essayer d'utiliser un nom logique au lieu d'un symbole DCL :

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

Utilisez sed.

Sed n'essaiera pas d'interpoler $data1 en tant que variable, vous devriez donc obtenir ce que vous voulez.

$ sed -e "s/baz/''mysub'/" file1.txt
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top