Подтвердить что ты не робот

Как правильно использовать имя переменной 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 в качестве новой необъявленной переменной.

Я попытался вставить двойные кавычки внутри обратных циклов, но выполнение кода остановилось без каких-либо сообщений.

Каков правильный способ вставки имен переменных в обратные ссылки для выполнения оболочки? Можно ли их конкатенировать?

4b9b3361

Ответ 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 );