PowerShell stripping double quotes from command line arguments

前端 未结 6 732
不思量自难忘°
不思量自难忘° 2020-11-28 05:42

Recently I have been having some trouble using GnuWin32 from PowerShell whenever double quotes are involved.

Upon further investigation, it appears PowerShell is str

6条回答
  •  -上瘾入骨i
    2020-11-28 06:16

    I personally avoid using '\' to escape things in PowerShell, because it's not technically a shell escape character. I've gotten unpredictable results with it. In double-quoted strings, you can use "" to get an embedded double-quote, or escape it with a back-tick:

    PS C:\Users\Droj> "string ""with`" quotes"
    string "with" quotes
    

    The same goes for single quotes:

    PS C:\Users\Droj> 'string ''with'' quotes'
    string 'with' quotes
    

    The weird thing about sending parameters to external programs is that there is additional level of quote evaluation. I don't know if this is a bug, but I'm guessing it won't be changed, because the behavior is the same when you use Start-Process and pass in arguments. Start-Process takes an array for the arguments, which makes things a bit clearer, in terms of how many arguments are actually being sent, but those arguments seem to be evaluated an extra time.

    So, if I have an array, I can set the argument values to have embedded quotes:

    PS C:\cygwin\home\Droj> $aa = 'arg="foo"', 'arg=""""bar""""'
    PS C:\cygwin\home\Droj> echo $aa
    arg="foo"
    arg=""""bar""""
    

    The 'bar' argument has enough to cover the extra hidden evaluation. It's as if I send that value to a cmdlet in double-quotes, then send that result again in double-quotes:

    PS C:\cygwin\home\Droj> echo "arg=""""bar""""" # level one
    arg=""bar""
    PS C:\cygwin\home\Droj> echo "arg=""bar""" # hidden level
    arg="bar"
    

    One would expect these arguments to be passed to external commands as-is, as they are to cmdlets like 'echo'/'write-output', but they are not, because of that hidden level:

    PS C:\cygwin\home\Droj> $aa = 'arg="foo"', 'arg=""""bar""""'
    PS C:\cygwin\home\Droj> start c:\cygwin\bin\echo $aa -nonew -wait
    arg=foo arg="bar"
    

    I don't know the exact reason for it, but the behavior is as if there is another, undocumented step being taken under the covers that re-parses the strings. For example, I get the same result if I send the array to a cmdlet, but add a parsing level by doing it through invoke-expression:

    PS C:\cygwin\home\Droj> $aa = 'arg="foo"', 'arg=""""bar""""'
    PS C:\cygwin\home\Droj> iex "echo $aa"
    arg=foo
    arg="bar"
    

    ...which is exactly what I get when I send these arguments to my external Cygwin instance's 'echo.exe':

    PS C:\cygwin\home\Droj> c:\cygwin\bin\echo 'arg="foo"' 'arg=""""bar""""'
    arg=foo arg="bar"
    

提交回复
热议问题