Come posso disabilitare l'interpolazione variabile con l'operatore di sostituzione perl?
Domanda
Sto cercando di sostituire una linea particolare in un file di testo su VMS.Normalmente, questo è un semplice unico rivestimento con Perl.Ma ho corso un problema quando il lato sostitutivo era un simbolo contenente un percorso VMS.Ecco il file e ciò che ho provato:
Contenuto di file1.txt:
foo
bar
baz
quux
.
Tentativo di sostituire la 3a riga:
$ mysub = "disk$data1:[path.to]file.txt"
$ perl -pe "s/baz/''mysub'/" file1.txt
.
Comporta la seguente uscita:
foo
bar
disk:[path.to]file.txt
quux
.
Sembra che Perl sia stato percorato e sostituito la parte $data1
del percorso con il contenuto di una variabile inesistente (cioè, niente).In esecuzione con il debugger lo ha confermato.Non ho fornito /e
, quindi pensavo che Perl debba semplicemente sostituire il testo AS-è.C'è un modo per ottenere Perl per farlo?
(nota anche che posso riprodurre un comportamento simile alla riga di comando Linux.)
Soluzione
Con il giusto mix di citazioni e doppie citazioni che puoi arrivare:
Creiamo una concatenazione stretta della "stringa" + "Simbolo sostitutivo" + "String". Le due doppie stringhe quotate contengono virgolette singole per il sostituto. Concetto ... Ma funziona.
$ perl -pe "s'baz'"'mysub'"'" file1.txt
.
Questa è una soluzione di livello DCL.
Per una soluzione perl, utilizzare l'operatore q()
per una stringa non interpolata ed eseguirlo.
Imparare il simbolo nella parente usando una semplice sostituzione DCL.
Questo è il mio preferito perché (quasi) ha senso per me e non è troppo confuso con citazioni.
$ perl -pe "s/baz/q(''mysub')/e" file1.txt
. Altri suggerimenti
come Ruakh scoperto quando si legge il mio commento, il problema dell'interpolazione Perl può essere risolto accedendo al %ENV
Hash, piuttostoche usare una variabile shell:
perl -pwe "s/baz/$ENV{mysub}/" file1.txt
.
Aggiunto -w
perché non credo in non usare warnings
anche in one-Liner.
Non ho nemmeno visto un sistema VMS in decenni, ma ... Escape Your Sigil?
$ mysub = "disk\$data1:[path.to]file.txt"
.
o forse
$ mysub = "disk\\$data1:[path.to]file.txt"
.
?
per sh
o un derivato, avrei usato
perl -pe'BEGIN { $r = shift(@ARGV) } s/baz/$r/' "$mysub" file1.txt
.
Altrimenti, devi in qualche modo nascosto il valore del mysub
in una stringa perl letterale.Sarebbe più complicato.Trova l'equivalente per il tuo guscio.
Edit by op:
Sì, funziona.L'equivalente VMS è
.perl -pe "BEGIN { $r = shift(@ARGV) } s/baz/$r/" 'mysub' file1.txt
Devi sfuggire al $
con \$
.Altrimenti Perl vede una variabile di riferimento e sostituisce la stringa $data1
con il contenuto di $data1
prima che venga valutata l'espressione regolare.Come non hai definito $data1
è, ovviamente, vuoto.
È possibile utilizzare il seguente codice:
$ mysub='disk\$data1:[path.to]file.txt'
$ perl -pe 's/baz/'$mysub'/' FILE
foo
bar
disk$data1:[path.to]file.txt
quux
. È possibile provare a utilizzare un nome logico invece di un simbolo DCL:
$ define mysub "disk$data1:[path.to]file.txt"
$ $ perl -pe "s/baz/mysub/" file1.txt
.
SED non proverà a interpolare $data1
come variabile, quindi dovresti ottenere ciò che desideri.
$ sed -e "s/baz/''mysub'/" file1.txt
.