Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

[Win32] Escaping quotes in perl one liner

by syphilis (Bishop)
on Nov 28, 2020 at 06:48 UTC ( #11124305=perlquestion: print w/replies, xml ) Need Help??

syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I run:
C:\_32>type try.pl open(my $x,">&STDOUT"); C:\_32>perl try.pl C:\_32>perl -le "open(my $x,\">&STDOUT\");" >& was unexpected at this time. C:\_32>
Why does the one-liner throw that error ?
Having escaped both double quotes I expected the one liner to behave in exactly the same way as the script - ie to simply silently exit.

I know that replacing the double quotes with singles works around the issue:
C:\_32>perl -le "open(my $x,'>&STDOUT');" C:\_32>
But is there a way to retain the use of double quotes and still get the one-liner to DWIM ?

Cheers,
Rob

Replies are listed 'Best First'.
Re: [Win32] Escaping quotes in perl one liner
by Corion (Pope) on Nov 28, 2020 at 06:57 UTC

    cmd.exe escapes double-quotes by doubling them:

    perl -le "open(my $x, "">&STDOUT"");"

    But usually, I prefer (for this reason) to rewrite oneliners using qq() and q(), which eliminates the need for knowing how to escape in this shell besides needing to know whether to use single or double quotes.

      perl -le "open(my $x, "">&STDOUT"");"

      Not quite - but close enough ;-)
      Thank you.
      Either of the following work and, AFAICT, are equivalent - though I'm not exactly sure why that equivalence should hold:
      perl -le "open(my $x, \"">&STDOUT"\");" perl -le "open(my $x, "\">&STDOUT\"");"
      So I gather it's just the way the shell functions (as opposed to an issue with perl), that I can do:
      C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = \"STDOUT\"; Dump $ar +g;" SV = PV(0x36cd1c) at 0x44b124 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x451dc4 "STDOUT"\0 CUR = 6 LEN = 10 COW_REFCNT = 1
      but it blows up as soon as I introduce shell metacharacters into the string:
      C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = \">&STDOUT\"; Dump $ +arg;" >& was unexpected at this time.
      And I guess the additional quotes provide the disambiguation required to allow the one-liner to DWIM.

      Cheers,
      Rob
Re: [Win32] Escaping quotes in perl one liner (updated)
by AnomalousMonk (Bishop) on Nov 28, 2020 at 07:05 UTC

    Some | The CMD MSDOS/Windows command line interpreter (God love it) requires, for some reason, that certain characters like & (there may be others (update: I believe & \ < > ^ | are all the characters that must be carat-escaped between backslash-escaped double-quotes)) that are between escaped double-quotes be escaped with a ^ (carat). Go figure.

    Win8 Strawberry 5.8.9.5 (32) Sat 11/28/2020 2:08:16 C:\@Work\Perl\monks\MikeTaylor >perl -Mstrict -Mwarnings -le "print \"&\", '\"&\"', '&';" Can't find string terminator '"' anywhere before EOF at -e line 1. '\", '\"' is not recognized as an internal or external command, operable program or batch file. '\"', '&';"' is not recognized as an internal or external command, operable program or batch file. Win8 Strawberry 5.8.9.5 (32) Sat 11/28/2020 2:08:48 C:\@Work\Perl\monks\MikeTaylor >perl -Mstrict -Mwarnings -le "print \"^&\", '\"^&\"', '&';" &"&"&

    Update: Changed example code to provide more instances of printing & | the presence of & inside versus outside escaped double-quotes.


    Give a man a fish:  <%-{-{-{-<

      that certain characters like & (there may be others) that are between escaped double-quotes be escaped with a ^ (carat).

      Yes ... that was the bit of information I was missing.
      I had tried using the stick on the on the > and the &, to no avail:
      C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = \"\>\&STDOUT\"; Dump + $arg;" The system cannot find the path specified. The system cannot find the path specified.
      But using the carrot works fine:
      C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = \"^>^&STDOUT\"; Dump + $arg;" SV = PV(0x2dcd2c) at 0x1c90564 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x1c8ff64 ">&STDOUT"\0 CUR = 8 LEN = 10 COW_REFCNT = 1
      Perhaps when the shell saw a backslash in those contexts, it might have been inclined to think "directory separator", so they had to come up with a different escape symbol.

      UPDATE: It seems that, even with q()and qq(), there are still times when the carat needs to be invoked as an escape:
      C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = q(">&STDOUT"); Dump +$arg;" >& was unexpected at this time. C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = q("^>^&STDOUT"); Dum +p $arg;" SV = PV(0x6bcd2c) at 0x57b30c REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x58056c ">&STDOUT"\0 CUR = 8 LEN = 10 COW_REFCNT = 1 C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = qq(">&STDOUT"); Dump + $arg;" >& was unexpected at this time. C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = qq("^>^&STDOUT"); Du +mp $arg;" SV = PV(0x6ccd2c) at 0x1e30fe4 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x1e6f47c ">&STDOUT"\0 CUR = 8 LEN = 10 COW_REFCNT = 1 C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = q(\">&STDOUT\"); Dum +p $arg;" >& was unexpected at this time. C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = q(\"^>^&STDOUT\"); D +ump $arg;" SV = PV(0x55cd2c) at 0x650274 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x690f5c "\">&STDOUT\""\0 CUR = 10 LEN = 12 COW_REFCNT = 1 C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = qq(\">&STDOUT\"); Du +mp $arg;" >& was unexpected at this time. C:\_32>perl -Mstrict -MDevel::Peek -le "my $arg = qq(\"^>^&STDOUT\"); +Dump $arg; " SV = PV(0x34cd34) at 0x1d8afbc REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0x1d905ac "\">&STDOUT\""\0 CUR = 10 LEN = 12 COW_REFCNT = 1 C:\_32>


      Cheers,
      Rob
        Perhaps when the shell saw a backslash in those contexts, it might have been inclined to think "directory separator", so they had to come up with a different escape symbol.

        Ah-ha. Yes, I think you're right! I've wondered about that for a long time. Thank you for dispelling my perplexity.


        Give a man a fish:  <%-{-{-{-<

Re: [Win32] Escaping quotes in perl one liner
by haukex (Bishop) on Nov 29, 2020 at 11:50 UTC

    FWIW, Win32::ShellQuote says: perl -le ^"open^(my $x,\^"^>^&STDOUT\^"^);^", which works, but is certainly not easy to type.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11124305]
Approved by marto
Front-paged by cguevara
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (2)
As of 2021-01-17 00:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?