web-dev-qa-db-ja.com

バックティック内で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を新しい宣言されていない変数と見なすためです。

バッククォート内に二重引用符を挿入しようとしましたが、コードの実行がメッセージなしで停止しました。

シェル実行のためにバックティックに変数名を挿入する適切な方法は何ですか?それらを連結できますか?

16
Joel G Mathew

補間文字列(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- quotes以外の場合は少し難しいです。解決策は、文字列全体を保持する一時変数を作成し、それを特別な引用符に補間することです。

    my $command = "mogrify -resize " . $wid . "x" . $hit. " *JPG";
    `$command`;
    

    これの変形は、sprintf補間を使用することです。

    my $command = sprintf 'mogrify -resize %dx%d *JPG', $wid, $hit;
    

余談ですが、多くのシェル補間の問題は、notバッククォートを使用し、代わりにopenまたはsystemを使用することで回避できます(出力が必要かどうかによって異なります)。

openの場合:

open my $command, "-|", "mogrify", "-resize", $wid . "x" . $hit, glob("*JPG")
  or die ...;

while (<$command>) { do something }

これはシェルを完全に回避するため(むしろ直接execs)、グロブは手動で行う必要があります。同じことが、複数の引数を持つsystemにも当てはまります。

23
amon

この問題はバックティックに固有のものではありません。この問題は、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
5
Dave Cross

他の適切な応答に加えて、 readpipe 関数を使用することもできます。これは、バッククォートおよびqx演算子と同等です。ただし、通常の関数と同様に、関数への引数の補間方法をより細かく制御できます。

$output = readpipe("mogrify -resize $wid" . "x$hit *.JPG");
$output = readpipe( sprintf "mogrify -resize %dx%d *.JPG", $wid, $hit );
3
mob