提问人:antonio 提问时间:3/23/2022 更新时间:11/16/2022 访问量:838
PowerShell:转义 CLI 调用的规则
PowerShell: escaping rules for CLI calls
问:
正如我所了解的,当使用 该选项从调用 PowerShell 时,转义规则本质上是 Linux 中使用的规则。因此,您使用反斜杠 (),而不是通常的反引号 ()。cmd.exe
-Command
\
`
这是说你不写:
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 时,有哪些等效命令?powershell.exe
cmd.exe
答:
TL的;博士
仅在 PowerShell 的命令行上,用于传递 () 应执行的代码。
\"
"
-c
-Command
只有在生成的代码中,PowerShell 通常的转义 as 才适用,因此你可能必须结合使用这两种转义技术:.
"
`"
`\"
- 您的尝试 ,具有相同的效果,但效果不佳。[1]
`""
- 您的尝试 ,具有相同的效果,但效果不佳。[1]
\"
在 PowerShell 自己对其命令行的分析方面可以可靠地工作,但可能会在cmd 端.exe
情况下中断调用 - 有关解决方法,请参阅底部。
从 PowerShell 调用 CLI(外部控制台应用程序)时,不仅 PowerShell 自己的引用规则首先应用不同的引用规则(支持字符串,嵌入在 Escaped as 中),PowerShell 7.2.x 之前的一个长期存在的错误还需要转义字符。 with 嵌入到外部程序参数中时(仅限);请看这个答案。
'...'
"
"..."
`"
"
\
此功能名为
PSNativeCommandArgumentPassing
洛伊此功能 - 在 PowerShell 7.3 中成为官方功能(请参阅此答案) - 不会发挥作用,因为:
它通常不可用(也不会)在通过其 CLI 调用的旧版 Windows PowerShell 版本中.exe而新式跨平台 PowerShell (Core) 版本的 CLI 是
pwsh.exe
)
它仅适用于来自 PowerShell 会话内部的调用。
它旨在解决从 PowerShell 调用具有嵌入或空字符串字符串参数的外部程序时长期存在的问题 - 请参阅此答案。
"
因此,链接的答案解决了您的最后一个问题:
-
另外,从 而不是 调用 PowerShell 时,有哪些等效命令?
powershell.exe
cmd.exe
-
简而言之:不幸的是,至少在 PowerShell 7.2.x 之前,您必须另外手动转义字符。
"
"
为什么以下工作原理:cmd.exe
powershell -c "echo \"That's a single quote: ' \""
PowerShell 仅在其命令行上将
\
识别为转义字符,以便与其他 CLI 保持一致。在 PowerShell 会话中,只有
'
(backtick) 用作转义字符。注意:虽然
\“
转义”
在 PowerShell(命令行解析)端的两个 PowerShell 版本中始终如一地工作,但在某些情况下,它可能会破坏cmd.exe
自己的解析 - 请参阅底部。
当 PowerShell CLI 通过 () 调用并带有一段要执行的 PowerShell 源代码时,该代码(以下参数)分两个阶段进行分析:
-c
-Command
-c
- 首先,所有未转义的字符都被剥离,转义的字符 () 被保留和未转义。
"
\"
- 只有这样,才会分析结果并作为 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 会话内部不会转义 -only 或 - 内部 ,或者 - do。\
"
`"
"..."
""
从上面可以看出为什么这(大部分)有效:
:: Works, but not robustly
powershell -nop -c "echo \"That's a double-quote: `"" \""
""
有时,但并不总是可以替代;[1] 这里确实如此 - 另请参阅底部。\"
因此,PowerShell 最终会逐字执行以下操作,这是有效的,因为传递的转义现在是 -escaped,因为它需要位于 PowerShell 字符串中:
"
`
"..."
echo "That's a double-quote: `" "
为了避免脆弱的逃逸,最好通过将所需的 -escaping 与命令行 -escaping - 相结合来制定此命令,即 - 但请参阅底部,了解完全健壮的解决方案:""
`
\
`\"
powershell -nop -c "echo \"That's a double-quote: `\" \""
避免 cmd
端的解析问题.exe是 \“
的安全替代方案:
虽然 \“
转义 ”
在 PowerShell(命令行解析)端的两个 PowerShell 版本中始终如一地工作,但在某些情况下,它可能会破坏 cmd.exe
自己的解析。相比之下,从无 shell 环境(如任务计划程序)调用时,使用是安全的。\"
虽然有一些解决方法,但不幸的是,它们是特定于 PowerShell 版本的:
在 Windows PowerShell 中 (
powershell.exe
)- 使用 (原文如此) 而不是
"^""
\"
- 使用 (原文如此) 而不是
在 PowerShell (Core) (v6+,
pwsh.exe
)- 使用代替
""
\"
- 使用代替
重要:
这些变通办法要求将传递给 () 的整个代码作为单个
“...”
括起来的参数传递。-c
-Command
-c
(-Command
) 还接受多个参数 - 可以单独使用双引号,也可以不使用双引号 - 在这种情况下,它只是在剥离未转义后将这些参数连接起来,以形成要执行的代码。这种技术在情境上允许你摆脱 -逃义(例如,,但 (a) 它要求你密切注意命令的哪些部分将被视为未加引号,(b) 需要你 -转义任何元字符,例如在这些部分中,以及 (c) 总是执行空格规范化,即将多个空格的运行折叠成一个空格。"
\"
powershell -c \"Between 2 & 3`\"\"
cmd.exe
^
cmd.exe
&
以下旨在逐字打印的调用演示了这一点: 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
,也是”^“”
)。
评论
!
powershell -c "echo \"That's a double-quote: !"" \""
echo "That's a double-quote: !"" "
""
"
powershell.exe
pwsh.exe
powershell.exe
echo "That's a double quote: `" "
""
powershell -c "echo \" Nat `""King`"" Cole \""
"
pwsh.exe
Nat "King" Cole
""
powershell.exe -c
\"
cmd.exe
"^""
)
评论