http://www.perlmonks.org?node_id=1033659

Ombongi.Moraa has asked for the wisdom of the Perl Monks concerning the following question:

I use this command to call the python script and pass arguments;

$output="sudo /usr/bin/python /home/processLog.py '$name' '$age' '$text' '$id' ";

return `$output`

However, as it is, bad problems arise when the $text variable contains single or double quotes. How can I pass the variables wholly esp with quotes within them?

Thanks in advance.

Replies are listed 'Best First'.
Re: Call Python script and pass arguments from Perl script (quotemeta)
by LanX (Saint) on May 15, 2013 at 11:01 UTC
    try quotemeta

    DB<109> $text=q{a'b"c}; print quotemeta($text) a\'b\"c DB<110> $name="Daffy Duck"; => "Daffy Duck" DB<111> print "'\Q$name\E' '\Q$text\E'" 'Daffy\ Duck' 'a\'b\"c'

    not sure if you really still need the single-quotes.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

    edit
    expanded example
Re: Call Python script and pass arguments from Perl script
by aitap (Curate) on May 15, 2013 at 11:02 UTC

    Try this:

    my $output=qq{sudo /usr/bin/python /home/processLog.py \Q$name\E \Q$ag +e\E \Q$text\E \Q$id\E}; return `$output`;
    It works using interpolating quote-like operator qq{} and escaping operators \Q...\E, both described in Quote and Quote like Operators.

    Another approach might be using open or modules like IPC::Run or IPC::Cmd to run a command with a list (not a string) of arguments:

    open my $fh, "-|", qw{sudo /usr/bin/python /home/processLog.py}, $name +, $age, $text, $id or die $!; return do {local $/; <$fh>};
    use IPC::Run; run [qw{sudo /usr/bin/python /home/processLog.py}, $name, $age, $text, + $id], ">", \(my $return) or die "run: $?"; return $return;

    Warning: all code in this message is untested.

    Update: using quotemeta for quoting shell commands is a hack, you should run a list of arguments instead, or use at least some shell-related module like String::ShellQuote.

    Update 2: the code I suggested will discard any newlines in the interpolated variables instead of escaping them properly, so I stroke it out. Thanks ambrus for correcting me.

    Edit: removed quotes from \Q...\E approach as they are entirely unnecessary in this case.
Re: Call Python script and pass arguments from Perl script
by ambrus (Abbot) on May 16, 2013 at 08:42 UTC

    I don't recommend using the quotemeta operator. That will usually misquote newlines with POSIX-like shells.

    Instead, skip the shell and use the multiple argument form pipe open, such as

    my $output; { my @command = "sudo", "/usr/bin/python", "/home/processLog.py", $n +ame, $age, $text, $id; open my $P, "-|", @command or die "error pipe opening program"; local $/; $output = <$P>; close $P or die "error: spawned program exited with failure or cannot read + pipe"; # note: you may want to accept an exit failure with some programs. + if you do, check eof($P) instead to catch a read error. } print $output;

    Update: added "skip the shell".