Как правильно использовать имя переменной perl в backticks?
Мне нужно выполнить следующий код в оболочке bash:
mogrify -resize 800x600 *JPG
Поскольку ширина и высота являются переменными, я пробовал это:
`mogrify -resize $widx$hit *JPG`
Однако в компиляции я получаю сообщение об ошибке Global symbol "$widx" requires explicit package name at getattach.pl line 131.
, потому что вместо $wid и x отдельно компилятор видит $widx в качестве новой необъявленной переменной.
Я попытался вставить двойные кавычки внутри обратных циклов, но выполнение кода остановилось без каких-либо сообщений.
Каков правильный способ вставки имен переменных в обратные ссылки для выполнения оболочки? Можно ли их конкатенировать?
Ответы
Ответ 1
Чтобы вставить переменную в любую интерполяционную строку (будь то qq//
или qx
или qr//
), достаточно выполнить только "this is $foo!"
: Имя переменной (здесь: $foo
) разделяется символом !
, который не может быть частью обычного имени переменной.
Не так просто, когда части строки могут быть частью имени по правилам именования Perl. Пример:
my $genes = "ACTG$insert_genes_hereACTG";
Perl считает имя переменной $insert_genes_hereACTG
. Это можно решить с помощью
-
Использование завитушек для ограничения имени:
my $genes = "ACTG${insert_genes_here}ACTG";
Это всегда работает и является гибким решением.
-
Объединение строки:
my $genes = "ACTG" . $insert_genes_here . "ACTG";
Это немного сложно для не-t210 > -quotes. Решением является создание временной переменной, которая содержит всю строку, а затем интерполирует ее на специальные кавычки:
my $command = "mogrify -resize " . $wid . "x" . $hit. " *JPG";
`$command`;
Вариант этого заключается в использовании интерполяции sprintf
:
my $command = sprintf 'mogrify -resize %dx%d *JPG', $wid, $hit;
В стороне, многие проблемы интерполяции оболочки можно обойти, не используя обратные обратные вызовы, и вместо этого использовать open
или system
(в зависимости от того, нужен ли вам вывод).
С open
:
open my $command, "-|", "mogrify", "-resize", $wid . "x" . $hit, glob("*JPG")
or die ...;
while (<$command>) { do something }
Это полностью обходит оболочку (и, скорее, exec
), так что глобулизация должна выполняться вручную. То же самое справедливо для system
с более чем одним аргументом.
Ответ 2
Эта проблема не относится к обратным вызовам. Проблема может возникать всякий раз, когда вы интерполируете переменные Perl в строке.
my $wid = 800;
my $hit = 600;
print "$widx$hit"; # this has the same problem
Проблема заключается в том, что компилятор Perl не может знать, где заканчивается имя переменной ( "wid" ) и начинается фиксированный бит строки ( "x" ). Поэтому он предполагает, что он ищет переменную с именем $widx
- которая не существует.
Решение состоит в том, чтобы поместить имя переменной в { ... }
.
my $wid = 800;
my $hit = 600;
print "${wid}x$hit"; # This works
Ответ 3
В дополнение к другим хорошим ответам вы также можете использовать функцию readpipe
, которая эквивалентна обратным выводам и qx
оператор. Но, как и регулярная функция, вы можете больше контролировать, как интерполируются аргументы.
$output = readpipe("mogrify -resize $wid" . "x$hit *.JPG");
$output = readpipe( sprintf "mogrify -resize %dx%d *.JPG", $wid, $hit );