Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Call Python script and pass arguments from Perl script

by Ombongi.Moraa (Novice)
on May 15, 2013 at 10:53 UTC ( #1033659=perlquestion: print w/replies, xml ) Need Help??
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/ '$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 (Bishop) 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)

    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/ \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/}, $name +, $age, $text, $id or die $!; return do {local $/; <$fh>};
    use IPC::Run; run [qw{sudo /usr/bin/python /home/}, $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/", $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".

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1033659]
Approved by marto
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2018-06-21 14:39 GMT
Find Nodes?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?

    Results (118 votes). Check out past polls.