Как отключить интерполяцию переменных с помощью оператора подстановки Perl?

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

  •  12-12-2019
  •  | 
  •  

Вопрос

Я пытаюсь заменить определенную строку в текстовом файле на VMS.Обычно это простая однострочная программа Perl.Но я столкнулся с проблемой, когда на заменяющей стороне был символ, содержащий путь VMS.Вот файл и то, что я пробовал:

Содержимое файла1.txt:

foo
bar
baz
quux

Попытка заменить 3-ю строку:

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

Дает следующий результат:

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

Похоже, Perl перестарался и заменил $data1 часть пути с содержимым несуществующей переменной (т. е. ничего).Запуск отладчика подтвердил это.я не поставлял /e, поэтому я подумал, что Perl должен просто заменить текст как есть.Есть ли способ заставить Perl сделать это?

(Также обратите внимание, что я могу воспроизвести подобное поведение в командной строке Linux.)

Это было полезно?

Решение

с просто правым смесью кавычек и двойных цитатов вы можете добраться туда:

Мы создаем герметичное соединение «строки» + «подстановочный символ» + «строка». Две двойные цитируемые строки содержат отдельные цитаты для заменителя. Подумал ... Но это работает.

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

Это решение уровня DCL.

Для решения Perl используйте оператор q() для неинтерполированной строки и выполните это. Протрите символ в парунге, используя простую замену DCL. Это мой любимый, потому что это (почти) имеет смысл для меня и не становится слишком запутанным с цитатами.

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

Другие советы

as Ruakh Обнаружены при прочтении моего комментария, проблема интерполяции Perl может быть решена путем доступа к генеракодичевому хешкоду, скорееЧем использовать переменную оболочки:

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

Добавлен генеракодицетагкод, потому что я не верю, что не использует %ENV даже в одноиналивах.

Даже не видел систему VMS в течение десятилетий, но ... сбежать вашего сигила?

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

или, возможно,

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

?

Для sh или производную, я бы использовал

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

В противном случае вам придется как-то скрыть значение mysub в строковый литерал Perl.Это было бы сложнее.Найдите эквивалент для вашей оболочки.

Редактировать ОП:

Да, это работает.Эквивалент VMS:

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

Вы должны избежать $ с \$.В противном случае Perl увидит ссылку на переменную и заменит строку. $data1 с содержанием $data1 перед вычислением регулярного выражения.Поскольку вы не определили $data1 оно, конечно, пустое.

Вы можете использовать следующий код:

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

Вы можете попробовать использовать логическое имя вместо символа DCL:

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

<Сильные> Использовать sed.

SED не попытается интерполировать $data1 в качестве переменной, поэтому вы должны получить то, что вы хотите.

$ sed -e "s/baz/''mysub'/" file1.txt
.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top