Como posso desabilitar a variável de interpolação com o Perl de substituição de operador?
Pergunta
Estou tentando substituir uma determinada linha em um arquivo de texto em VMS.Normalmente, esta é uma simples linha com Perl.Mas eu tive um problema quando a substituição lado era um símbolo contém uma VMS caminho.Aqui está o arquivo e o que eu tentei:
Conteúdo file1.txt:
foo
bar
baz
quux
Tentativa de substituto de 3ª linha:
$ mysub = "disk$data1:[path.to]file.txt"
$ perl -pe "s/baz/''mysub'/" file1.txt
Produz a seguinte saída:
foo
bar
disk:[path.to]file.txt
quux
Parece que o Perl foi overeager e substituiu o $data1
parte do caminho com o conteúdo de um inexistente variável (isto é, nada).Execução com o depurador confirmou que.Eu não fornecimento /e
, então eu pensei em Perl deve apenas substituir o texto como está.Existe uma maneira de obter o Perl para fazer isso?
(Note também que eu possa reproduzir um comportamento semelhante no linux a linha de comando.)
Solução
Com a mistura certa de aspas e aspas duplas você pode chegar lá:
Criamos um apertado concatenação de "cadeia de caracteres" + 'substituto símbolo" + "cadeia".As duas seqüências de caracteres entre aspas conter aspas simples para o substituto.Teceu...mas funciona.
$ perl -pe "s'baz'"'mysub'"'" file1.txt
Essa é uma DCL nível de solução.
Para um Perl solução, use o q()
operador para um não-interpolados cadeia e executar.Coisas que o símbolo no parens usando simples DCL substituição.Este é o meu favorito, porque (quase) faz todo o sentido para mim, e não ficar muito confuso com aspas.
$ perl -pe "s/baz/q(''mysub')/e" file1.txt
Outras dicas
Como ruakh descobriu ao ler o meu comentário, o problema do perl de interpolação podem ser resolvidos por acessar o %ENV
hash ao invés de usar uma variável de shell:
perl -pwe "s/baz/$ENV{mysub}/" file1.txt
Adicionado -w
porque eu não acredito em não warnings
mesmo em one-liners.
Ainda não vi um sistema VMS em décadas, mas ...escapar de seu brasão?
$ mysub = "disk\$data1:[path.to]file.txt"
ou talvez
$ mysub = "disk\\$data1:[path.to]file.txt"
?
Para sh
ou um derivado, eu usaria
perl -pe'BEGIN { $r = shift(@ARGV) } s/baz/$r/' "$mysub" file1.txt
Caso contrário, você precisa de alguma forma de converter o valor de mysub
em um Perl de seqüência de caracteres literal.Que seria mais complicado.Encontrar o equivalente para o seu shell.
Editar pelo OP:
Sim, isso funciona.O VMS equivalente é
perl -pe "BEGIN { $r = shift(@ARGV) } s/baz/$r/" 'mysub' file1.txt
Você tem que escapar do $
com \$
.Caso contrário, Perl vê uma variável de referência e substitui a cadeia $data1
com o conteúdo de $data1
antes de regular a expressão é avaliada.Como você não definir $data1
é, claro, vazio.
Você pode usar o seguinte código :
$ mysub='disk\$data1:[path.to]file.txt'
$ perl -pe 's/baz/'$mysub'/' FILE
foo
bar
disk$data1:[path.to]file.txt
quux
Você pode tentar usar um nome lógico, em vez de uma DCL símbolo:
$ define mysub "disk$data1:[path.to]file.txt"
$ $ perl -pe "s/baz/mysub/" file1.txt
Usar o sed.
Sed não tente interpolar $data1
como uma variável, então você deve obter o que deseja.
$ sed -e "s/baz/''mysub'/" file1.txt