Как правильно использовать имя переменной 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, Это может быть решено

  1. Использование фигурных скобок для разделения имени:

    my $genes = "ACTG${insert_genes_here}ACTG";
    

    Это всегда работает и является гибким решением

  2. Конкатенация строки:

    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 );
Другие вопросы по тегам