Home > Enterprise >  Perl backticks using bash
Perl backticks using bash

Time:02-09

In Perl, the default shell to execute backticks is sh. I'd like to switch to use bash for its richer syntax. So far I found that the suggested solution is

`bash -c \"echo a b\"`

The apparent drawback is that the escaped double quotes, which means I will have difficulty to use double quotes in my bash args. For example, if I wanted to run commands requiring double quotes in bash

echo "a'b"

The above method will be very awkward.

Perl's system() call has a solution for this problem: to use ARRAY args,

system("bash", "-c", qq(echo "a'b"));

This keeps my original bash command unmodified, and almost always.

I'd like to use ARRAY args in backticks too. Is it possible? Thank you for your advice

CodePudding user response:

You can use single quotes as delimiter with qx like this:

my $out = qx'bash -c "echo a b"';

this will according to perlop protect the command from Perl's double-quote interpolation.

Unfortunately, this does not work for single quotes. If you want to do echo "'" for example, you need the following:

my $out = `bash -c \"echo \\\"'\\\"\"`;

Edit:

To help you managing the escaping of quotes you could use a helper function like this:

use experimental qw(signatures);
sub bash_backticks($code) {
    $code =~ s/'/'"'"'/g;
    `bash -c '$code'`
}

CodePudding user response:

I have the following sub that works

    sub bash_output {
       my ($cmd) = @_; 
    
       open my $ifh, "-|", "bash", "-c", $cmd or die "cannot open file handler: $!";
    
       my $output = ""; 
       while (<$ifh>) {
          $output .= $_; 
       }   
    
       close $ifh;
    
       return $output;
    }

    print "test bash_output()\n";

    my @strings = (
         qq(echo "a'b"),
         'echo $BASH_VERSION',
         '[[ "abcde" =~ bcd ]] && echo matched',
         'i=1; ((i  )); echo $i',
   );

   for my $s (@strings) {
         print "bash_output($s) = ", bash_output($s), "\n";
   }

The output is

bash_output(echo "a'b") = a'b

bash_output(echo $BASH_VERSION) = 4.4.20(1)-release

bash_output([[ "abcde" =~ bcd ]] && echo matched) = matched

bash_output(i=1; ((i  )); echo $i) = 2

My answer is long-winded but it fills my need. I was hoping Perl has a built-in solution just like how it handles system() call and I am still hoping.

CodePudding user response:

You can change the shell used by perl :

$ENV{PERL5SHELL} = "bash";
my $out = qx{echo "Hello ' world from bash \$BASH_VERSION"};
print($out);
  •  Tags:  
  • Related