How do I use a perl variable name properly within backticks?

前端 未结 3 587
心在旅途
心在旅途 2020-12-30 04:01

I need to execute the following code on a bash shell:

mogrify -resize 800x600 *JPG

Since the width and height are variables, I tried this:<

相关标签:
3条回答
  • 2020-12-30 04:08

    This problem isn't specific to backticks. The problem can happen whenever you interpolate Perl variables in a string.

    my $wid = 800;
    my $hit = 600;
    
    print "$widx$hit"; # this has the same problem
    

    The problem is that the Perl compiler can't know where the variable name ("wid") ends and the fixed bit of the string ("x") starts. So it assumes that it is looking for a variable called $widx - which doesn't exist.

    The solution is to put the name of the variable in { ... }.

    my $wid = 800;
    my $hit = 600;
    
    print "${wid}x$hit"; # This works
    
    0 讨论(0)
  • 2020-12-30 04:09

    To insert a variable into any interpolating string (be it qq// or qx or qr//), just doing "this is $foo!" is sufficient: The variable name (here: $foo) is delimited by the ! which cannot be part of a normal variable name.

    It is not so easy when parts of the string could be part of the name by Perl's naming rules. Example:

    my $genes = "ACTG$insert_genes_hereACTG";
    

    Perl considers the variable name to be $insert_genes_hereACTG. This can be solved by

    1. Using curlies to delimit the name:

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

      This always works and is a flexible solution

    2. Concatenating the string:

      my $genes = "ACTG" . $insert_genes_here . "ACTG";
      

      This is a bit difficult for non-qq-quotes. A solution is to create a temporary variable that holds the whole string, and then interpolates it into special quotes:

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

      A variant of this is to use sprintf interpolation:

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

    As an aside, many shell interpolation problems can be circumvented by not using backticks, and using open or system instead (depending on whether or not you need output).

    With open:

    open my $command, "-|", "mogrify", "-resize", $wid . "x" . $hit, glob("*JPG")
      or die ...;
    
    while (<$command>) { do something }
    

    This completely circumvents the shell (and rather execs directly), so globbing has to be done manually. The same holds true for system with more than one argument.

    0 讨论(0)
  • 2020-12-30 04:11

    In addition to the other good responses, you can also use the readpipe function, which is equivalent to backticks and the qx operator. But like a regular function, you can exercise greater control over how the arguments to it are interpolated.

    $output = readpipe("mogrify -resize $wid" . "x$hit *.JPG");
    $output = readpipe( sprintf "mogrify -resize %dx%d *.JPG", $wid, $hit );
    
    0 讨论(0)
提交回复
热议问题