Как отключить интерполяцию переменных с помощью оператора подстановки Perl?
Вопрос
Я пытаюсь заменить определенную строку в текстовом файле на 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
.