Question

I have ran into a situation where single quotes are causing Bash 'unterminated quoted string' errors in a system call. In this specific case I am trying to interpolate the $DBI::errstr into the bash commands. I am using in the system call:

system "echo '$DBI::errstr' | mail -s 'error' usr@mail.com";

So $DBI::errstr sometimes contains single quotes and causes errors. I know I can just enclose $DBI::errstr in back-slashed double quotes \"$DBI::errstr\" and call it a day, but there must be a better way to handle the quotes with out regex or writing a sub routine, which I am having trouble finding. I have also tried quotemeta but this will back-slash the spaces too.

Was it helpful?

Solution

There is no good reason to use system echo in Perl. You can simply open a pipe as a filehandle and print to it:

open my $mail, '|-', qw/mail -s error usr@mail.com/ or die $!;
print $mail $DBI::errstr, "\n";

EDIT: but to answer your question in more generality. Instead of relying on the shell to parse and unquote your command-line string and turn it into arguments, it's usually a better idea to use the explicit multi-argument form of system(). So, instead of system "some_command --arg=$val" and worrying whether $val needs to be quoted for the shell, you can use system("some_command", "--arg=$val").

OTHER TIPS

If you were going to use system, this is what you'd do:

use String::ShellQuote qw( shell_quote );

my $cmd1 = shell_quote('echo', $DBI::errstr);
my $cmd2 = shell_quote('mail', '-s', 'error', $email_addr);
system("$cmd1 | $cmd2");
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top