PowerShell:CLI 调用的转义规则

PowerShell: escaping rules for CLI calls

据我了解,当使用 -Command 选项从 cmd.exe 调用 PowerShell 时,转义规则基本上是 Linux 中使用的规则。所以你使用反斜杠 (\),而不是通常的反引号 (`).

这就是说你不写:

C:\> powershell -c "echo `"That's a single quote: ' `""

但是

C:\> powershell -c "echo \"That's a single quote: ' \""

获得:

That's a single quote: '

这与您在 Linux 终端中键入的内容完全相同:

~ >>> bash -c "echo \"That's a single quote: ' \""                                                                      

如果我没记错的话,这个功能被命名为 PSNativeCommandArgumentPassing。 但是比较在一定程度上起作用。事实上,在 Linux 下你写:

~ >>> bash -c "echo \"That's a double quote: \\" \""                                                              

获得:

That's a double quote: " 

而等效的 PowerShell 行:

C:\> powershell -c "echo \"That's a double quote: \\"  \""

给予

The string is missing the terminator: ".

通过反复试验,我意识到:

C:\> powershell -c "echo \"That's a double-quote: `""  \""

按预期工作。

你能给我解释一下背后的逻辑是什么吗:`""?

此外,从 powershell.exe 而不是 cmd.exe 调用 PowerShell 时等效的命令是什么?

tl;dr

  • 仅在 PowerShell 的 命令行上 ,使用 \"" 传递给 -c 的代码(-Command) 应该执行。

    • 只有在生成的代码中 PowerShell 通常将 " 转义为 `" 适用,因此您可能必须 组合 两种转义技术:`\".

      • 您的尝试,`"",具有相同的效果,但效果不佳可靠[1]
    • \" 在 PowerShell 自身对其命令行的解析方面运行稳定,但在 cmd.exe 端 可能会中断调用 ] - 请参阅底部的解决方法。

  • 从 PowerShell 调用 CLI(外部控制台应用程序) 时,不仅 PowerShell 自己的,首先应用不同的引用规则(支持 '...'字符串,嵌入 "..." 内的 " 转义为 `"),一个 long-standing 错误至少达到 PowerShell 7。2.x 另外 需要转义 " 个字符。当嵌入 external-program 参数时使用 \(仅限);参见


this feature is named PSNativeCommandArgumentPassing

否;此功能 - 从 PowerShell 7.2.2 开始实验。 - 没有发挥作用,因为:

  • 它通常不会(也不会)在您通过其调用的旧版 Windows PowerShell CLI,powershell.exe (whereas the modern, cross-platform PowerShell (Core) edition's CLI is pwsh.exe)

  • 它仅适用于来自内部 PowerShell 会话的调用。

  • 它旨在解决 long-standing 使用嵌入式 " 或 empty-string 字符串参数调用外部程序时的问题 from PowerShell - 请参阅 .

    • 因此,链接的答案解决了您的最后一个问题:

      • Also, what are the equivalent commands when calling PowerShell from powershell.exe, rather than cmd.exe?

    • 简而言之:不幸的是,至少要达到 PowerShell 7。2.x您还必须另外,手动转义" 字符。 " 嵌入在 external-program 个参数中(仅)。


为什么以下内容来自 cmd.exe

powershell -c "echo \"That's a single quote: ' \""
  • PowerShell 仅将 \ 识别为转义字符 在其命令行 , 以与其他 CLI。

    • PowerShell会话中,只有`(反引号)用作转义符。

    • 警告:虽然 \" 转义 " 在两个 PowerShell 中始终如一地工作 版本 PowerShell(command-line 解析)端 ,在某些情况下它 可以破坏 cmd.exe 的自己的解析 - 请参阅底部。

  • 当通过 -c (-Command) 调用 PowerShell CLI 并执行一段 PowerShell 源代码时,该代码([= 后面的参数) 20=]分两个阶段解析:

    • 首先,所有 未转义 " 个字符。是 剥离的 ,其中 转义的 (\") 被保留且未转义。
    • 只有then的结果被解析并作为PowerShell代码.
    • 执行

因此,PowerShell 最终执行的是逐字的:

echo "That's a single quote: ' "

从上面可以看出为什么这有效:

:: SYNTAX ERROR
powershell -c "echo \"That's a double quote: \\"  \""

PowerShell 最终尝试逐字执行

echo "That's a double quote: \" "

这是一个语法错误,因为 中,PowerShell 会话\ 不会转义" -仅 `" 或 - 在 "..." 内,或者 - "" do.


从上面可以看出为什么这(大部分)有效:

:: Works, but not robustly
powershell -nop -c "echo \"That's a double-quote: `""  \""
  • "" 有时,但并不总是替代 \";[1] 在这里 - 另见底部部分。

  • 因此,PowerShell 最终逐字执行了以下命令,这是有效的,因为通过的转义 " 现在是 `-转义,因为它需要在 PowerShell "..." 字符串中:

     echo "That's a double-quote: `"  "
    

为了避免脆弱的 "" 转义,最好通过将所需的 `-转义与 command-line \-转义相结合来制定此命令 - 即`\" - 但请参阅底部部分以获得完全可靠的解决方案:

powershell -nop -c "echo \"That's a double-quote: `\"  \""

避免解析问题cmd.exe\"的安全替代:

虽然 \" 转义 " 在两个 PowerShell 版本 PowerShell[=282] 中一致 =] (command-line parsing) side,在某些情况下它 可以破坏 cmd.exe 自己的解析 。相比之下,使用\"no-shell 环境(如任务计划程序)调用时是安全的。

虽然有解决方法,但不幸的是,PowerShell edition-specific:

  • Windows PowerShell (powershell.exe)

    • 使用 "^""(原文如此)代替 \"
  • PowerShell(核心)(v6+,pwsh.exe

    • 使用""代替\"

重要:

  • 这些解决方法需要 整个代码传递给-c (-Command) 作为单个传递,"..."-封闭参数.

  • -c (-Command) 也接受 多个 参数 - 可能 单独 是 double-quoted 还是不是 - 在这种情况下,它只是简单地连接这些参数,在剥离未转义的 " 之后,以形成要执行的代码。这种技术在某些情况下允许您摆脱 \" 转义(例如 powershell -c \"Between 2 & 3`\"\",但是 (a) 它要求您密切注意命令 cmd.exe 的哪些部分将被视为unquoted,(b) 会要求您 ^-转义那些部分中的任何 cmd.exe 元字符,例如 &,并且 (c) 总是执行空白规范化,即将多个个空格分别折叠成一个。

以下调用旨在逐字打印  Between 2 & 3" ,证明了这一点:

:: BREAKS, because cmd.exe sees `&` as *outside a double-quoted string*
powershell -c " \" Between 2 & 3`\" \" "

:: PowerShell (Core) workaround
pwsh -c " "" Between 2 & 3`"" "" "

:: Windows PowerShell workaround
powershell -c " "^"" Between 2 & 3`"^"" "^"" "

[1] "..." 中的 "" 工作的一个例子是 powershell -c "echo \" Nat `""King`"" Cole \"":在 Nat "King" Cole 中,它打印 Nat "King Cole,即缺少第二个转义的 "(它在 pwsh.exe 中可以正常工作,如底部部分所述)。最终不值得推测 "" 序列是如何被 powershell.exe -c 准确解析的,因为它显然不可靠并且确实存在可靠的替代方案(\" 或者,来自 cmd.exe, 还有 "^"").