Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re: Running command with backslash not working as expected

by haukex (Archbishop)
on May 09, 2019 at 08:08 UTC ( [id://1233487]=note: print w/replies, xml ) Need Help??


in reply to Running command with backslash not working as expected

Backticks interpolate backslash escapes just like double quotes (the only exception being qx'...' ), while single quotes do not (Quote and Quote like Operators).

`$_vim_cmd  . ' -c "normal \r" -c wq ~/vimwiki/testing.md'`;

What's being passed to the external command* is a literal carriage return byte (despite all the extra quotes around it - Perl doesn't care about quotes within quotes).

my $value = ' -c "normal \r" -c wq ~/vimwiki/testing.md'; `$_vim_cmd  $value`;

Here, you're setting up a Perl string to contain the two-byte string \ plus r, and passing that to backticks, so that two-byte string then becomes part of the argument list*.

(* Update: To clarify, what I mean is that this is Perl's interpretation of the string - what the external command actually receives in its argv after the string is optionally passed through the shell is a different matter, as the following explains.)

use warnings; use strict; use Data::Dump; my $perl = "$^X -wMstrict -MData::Dump -e 'dd\\\@ARGV' -- "; dd qq{'"normal \r"'}; # prints "'\"normal \r\"'" print `$perl '"normal \r"'`; # => @ARGV is ("\"normal \r\"") my $value = '"normal \r"'; dd qq{$value}; # prints "\"normal \\r\"" print `$perl $value`; # => @ARGV is ("normal \\r") # "strace -s256 -fe trace=execve" (abbreviated by me) shows: # execve("/bin/sh", ["sh", "-c", "perl ... -- '\"normal \r\"'"], ... # execve("/bin/sh", ["sh", "-c", "perl ... -- \"normal \\r\""], ...

Since you don't say what your desired result is, it's unclear to me what you mean by "works" and "doesn't work", but IMO this is another great reason to avoid the shell - as you can see above, Perl is calling the shell, and since it's unclear what this "default shell" is, this code is not going to be portable. It'd be better if you use something like capturex from IPC::System::Simple and then use Perl's normal quoting mechanisms to set up the exact strings that you want to get passed to the external process.

use IPC::System::Simple qw/capturex/; print capturex($^X, qw/ -wMstrict -MData::Dump -e dd@ARGV -- /, "\r", "\\r"); # => prints ("\r", "\\r")

Plus, all the other advice from my node here applies as well, e.g. you should check $? for errors. Also, using backticks in void context doesn't make much sense, maybe you want system instead? That supports avoiding the shell without having to pull in an extra module.

Replies are listed 'Best First'.
Re^2: Running command with backslash not working as expected
by nysus (Parson) on May 09, 2019 at 13:00 UTC

    Thanks. system results in a lot of unwanted ugliness to the screen. Besides, system returns a response code which I'm just going to throw away. Plus backticks are faster to type and less cluttering.

    $PM = "Perl Monk's";
    $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
    $nysus = $PM . ' ' . $MCF;
    Click here if you love Perl Monks

      system results in a lot of unwanted ugliness to the screen.

      There are ways to work around that. Many commands support a --quiet switch, which is my preferred method because I usually want to see external command's output to be able to inspect it for problems, or you could use another module to capture the command's STDOUT to suppress it.

      system returns a response code which I'm just going to throw away.

      I don't understand this argument - you're throwing away the backtick's return value as well... Plus, why would you call a command and then ignore whether it was successful or not?

      backticks are faster to type and less cluttering.

      Backticks don't offer a way to avoid the shell.

        I'm launching vim with the commands. I already have tests to see if vim is installed and executes properly. I only care about whether the manipulations of file vim operates upon work.

        $PM = "Perl Monk's";
        $MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon Curate Priest Vicar";
        $nysus = $PM . ' ' . $MCF;
        Click here if you love Perl Monks

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1233487]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (6)
As of 2024-04-23 15:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found