owerShell——在PowerShell收到命令之前,它们仍然会被cmd剥离

owerShell——在PowerShell收到命令之前,它们仍然会被cmd剥离,powershell,cmd,escaping,Powershell,Cmd,Escaping,好消息是,使用cmd字符串替换方法,这是可以克服的。设置x的初始值后,执行以下cmd命令: 将'替换为',以转义PowerShell的单引号: G:\test.ps1 -name "value of x, which may contain 's" -data 'value of y' set x=%x:'=''% 将“替换为\”,以转义cmd的双引号: set x=%x:"=\"% 这两项作业的顺序并不重要 现在,可以使用OP最初使用的语法调用PowerShell脚本(删除PowerS

好消息是,使用cmd字符串替换方法,这是可以克服的。设置x的初始值后,执行以下cmd命令:

  • '
    替换为
    '
    ,以转义PowerShell的单引号:

    G:\test.ps1 -name "value of x, which may contain 's" -data 'value of y'
    
    set x=%x:'=''%
    
  • 替换为
    \”
    ,以转义cmd的双引号:

    set x=%x:"=\"%
    
    这两项作业的顺序并不重要

  • 现在,可以使用OP最初使用的语法调用PowerShell脚本(删除PowerShell.exe的路径以将其全部放在一行中):

  • 同样,如果应用程序只能向cmd发送一行命令,那么这三个命令可以放在一个批处理文件中,应用程序可以调用批处理文件并传递如上所示的变量(我原始答案中的第一个项目符号)

    值得注意的一点是,如果用
    \“
    替换
    是内联完成的,而不是使用单独的set命令,则不会在字符串替换中转义
    ,即使它们位于双引号字符串中,例如:

    C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass "G:\test.ps1 -name '%x' -data '%y'"
    
    path\test.bat "%x%" "%y%"
    
    powershell.exe -ExecutionPolicy Bypass "G:\test.ps1 -name '%x:"=\"' -data '%y'"
    
    powershell.exe -ExecutionPolicy Bypass "G:\test.ps1 -name '%x:\"=\\"' -data '%y'"
    
    不是这样的:

    C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass "G:\test.ps1 -name '%x' -data '%y'"
    
    path\test.bat "%x%" "%y%"
    
    powershell.exe -ExecutionPolicy Bypass "G:\test.ps1 -name '%x:"=\"' -data '%y'"
    
    powershell.exe -ExecutionPolicy Bypass "G:\test.ps1 -name '%x:\"=\\"' -data '%y'"
    

    我不清楚
    %x
    %y
    是否是CMD变量(在这种情况下,您应该使用
    %x%
    替换它,或者在其他应用程序中进行替换)

    您需要在CMD.EXE命令行中将传递给PowerShell的单引号加倍,从而对其进行转义。您可以用两个单引号替换变量中的任何引号

    例如:

    C:\scripts>set X=a'b
    
    C:\scripts>set Y=c'd
    
    C:\scripts>powershell .\test.ps1 -name '%x:'=''%' '%y:'=''%'
    Name is 'a'b'
    Data is 'c'd'
    
    其中
    test.ps1
    包含:

    C:\scripts>type test.ps1
    param($name,$data)
    
    write-output "Name is '$name'"
    write-output "Data is '$data'"
    
    如果您给出的命令行是在外部应用程序中生成的,那么您仍然可以通过首先将字符串分配给变量并使用
    &
    分隔命令来完成此操作(小心避免
    set
    命令上的尾随空格)

    CMD shell支持简单的替换形式,以及在替换变量时提取替换字符串的方法。这些方法仅在替换变量时有效,因此,如果您希望同时执行多个替换,或替换和替换字符串提取,则需要在每个步骤中一次执行一个设置变量

    Environment variable substitution has been enhanced as follows:
    
        %PATH:str1=str2%
    
    would expand the PATH environment variable, substituting each occurrence
    of "str1" in the expanded result with "str2".  "str2" can be the empty
    string to effectively delete all occurrences of "str1" from the expanded
    output.  "str1" can begin with an asterisk, in which case it will match
    everything from the beginning of the expanded output to the first
    occurrence of the remaining portion of str1.
    
    May also specify substrings for an expansion.
    
        %PATH:~10,5%
    
    would expand the PATH environment variable, and then use only the 5
    characters that begin at the 11th (offset 10) character of the expanded
    result.  If the length is not specified, then it defaults to the
    remainder of the variable value.  If either number (offset or length) is
    negative, then the number used is the length of the environment variable
    value added to the offset or length specified.
    
        %PATH:~-10%
    
    would extract the last 10 characters of the PATH variable.
    
        %PATH:~0,-2%
    
    would extract all but the last 2 characters of the PATH variable.
    

    尝试将随机单引号变量封装在一对双引号中以避免问题

    C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass "G:\test.ps1 -name `"%x`" -data `"%y`""
    

    出现问题的原因是您使用了单引号,并且在单引号愚弄PowerShell中出现了随机的额外单引号。如果使用反勾号双引号,则不应出现这种情况,因为单引号不会在双引号中抛出任何内容,反勾号将允许您双引号/双引号。

    仅供参考,我遇到了powershell中的robocopy命令出现一些问题,并且希望排除名称中带有单引号的文件夹(反引号没有帮助,ps和robocopy不能使用双引号);因此,我只需为文件夹创建一个带有引号的变量即可解决此问题:

    $folder="John Doe's stuff"
    robocopy c:\users\jd\desktop \\server\folder /mir /xd 'normal folder' $folder
    

    解决此问题的一种奇怪方法是在cmd中使用echo将命令管道传输到“powershell-c”-“,而不是使用powershell”参数”

    例如:

    ECHO Write-Host "stuff'" | powershell -c "-"
    
    输出:

    stuff'
    
    几点注意:

  • 不要引用您正在回显的命令文本,否则它将不起作用

  • 如果要在PowerShell命令中使用任何管道,它们必须使用克拉进行三次转义才能正常工作

    ^^^|


  • 但这不是他要问的。他不是要问如何转义周围的单引号——事实上,这没有意义,因为在cmd中不需要转义引号字符串中的单引号(正如您使用
    ^
    所暗示的),也不需要转义PowerShell中字符串参数周围的单引号。他要问的是如何转义cmd变量%x的值中可能出现的任何单引号,这样,如果例如%x=
    foo'bar
    ,他就没有通过test.ps1脚本参数
    -name'foo'bar'
    ,这将导致缺少终止符错误。这实际上比您想象的要复杂得多——在从cmd传递到PowerShell的字符串中转义嵌套引号是一个非常头痛的问题。让我试验几分钟,我应该能够想出一个解决方案。PowerShell的哪个版本?实际上,现在我已经考虑过了,将其更改为处理插值sp特殊字符非常简单。我会更新答案。嘿,谢谢你的信息!%x基本上可以是任何字符串(它是文件夹名称)。字符串几乎总是字母和数字,但有时它也可以包含单引号或双引号。其余的并不重要,但这两个都重要。它还应该与空格一起使用。哇,不像我最初想的那么简单!我能够为你问的原始问题想出一个笨拙的解决方案。但是,你这里说%x可能包含双引号,这破坏了您原来的命令和我的解决方法,我认为没有第三方实用程序就无法解决这个问题。我将在我的答案更新中解释。谢谢!在这种情况下,我可能会使用您已经发布的解决方案。单引号在十个以上的双引号,所以我就不提了。好吧,但请记住,如果x也包含
    $
    `
    ,我的第一个解决方案就失效了。我刚才添加的复杂解决方案适用于除双引号以外的任何内容。现在我已经发布了它,是时候让其他人发布一个非常简单的解决方案了我的头撞在墙上。;)啊,我明白你在做什么了!起初我有点困惑,以为你犯了和瓦西里一样的错误,但现在有了道理——这是我一直在寻找的,但找不到的,一种替换字符串的方法
    C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass "G:\test.ps1 -name `"%x`" -data `"%y`""
    
    $folder="John Doe's stuff"
    robocopy c:\users\jd\desktop \\server\folder /mir /xd 'normal folder' $folder
    
    ECHO Write-Host "stuff'" | powershell -c "-"
    
    stuff'