Как правильно использовать имя переменной perl в обратных галочках?
Мне нужно выполнить следующий код в оболочке 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 как новую необъявленную переменную.
Я попытался вставить двойные кавычки в обратные кавычки, но выполнение кода остановилось без каких-либо сообщений.
Как правильно вставлять имена переменных в backticks для выполнения оболочки? Могут ли они быть объединены?
3 ответа
Вставить переменную в любую интерполирующую строку (будь то 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";
Это немного сложно для
qq
-цитаты. Решением является создание временной переменной, которая содержит всю строку, а затем интерполирует ее в специальные кавычки: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
с более чем одним аргументом.
Эта проблема не характерна для обратных кавычек. Проблема может возникнуть всякий раз, когда вы интерполируете переменные 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
В дополнение к другим хорошим ответам, вы также можете использовать readpipe
функция, которая эквивалентна обратным меткам и тому qx
оператор. Но, как и обычная функция, вы можете осуществлять больший контроль над тем, как ее аргументы интерполируются.
$output = readpipe("mogrify -resize $wid" . "x$hit *.JPG");
$output = readpipe( sprintf "mogrify -resize %dx%d *.JPG", $wid, $hit );