powershell - Start-Process with PowerShell.exe 表现出嵌入单引号和双引号的不同行为
问题描述
首先,如果有人想知道我们为什么要以这种方式调用 PowerShell,我在构建的一个更复杂的命令中遇到了这种行为,但可以使用如下所示的更简单的示例来展示这种行为。在实践中,我们以管理员身份在 32 位 PowerShell 下运行命令,并在字符串中呈现附加变量(因此我不简单地使用单引号作为外部部分),但这似乎并没有考虑到下面的行为。
当我通过 调用 PowerShell 时,如果我在 PowerShell 可执行文件Start-Process
的参数周围使用单引号,我会得到一些奇怪的行为。-Command
例如:
Start-Process -FilePath Powershell.exe -ArgumentList "-Command 'ping google.com'"
只是呈现ping google.com
为输出并退出。但是,如果我使用嵌套的双引号而不是单引号,如下所示:
Start-Process -FilePath Powershell.exe -ArgumentList "-Command `"ping google.com`""
ping
运行并产生预期的输出:
使用 32 字节数据 ping google.com [173.194.78.113]:
来自 173.194.78.113 的回复:字节=32 时间=34ms TTL=45
来自 173.194.78.113 的回复:字节=32 时间=33ms TTL=45
来自 173.194.78.113 的回复:字节=32 时间=35ms TTL=45
来自 173.194.78.113 的回复:字节=32 时间=32ms TTL=45
173.194.78.113 的 Ping 统计信息:
数据包:发送 = 4,接收 = 4,丢失 = 0(丢失 0%),
大约以毫秒为单位的往返时间:
最小值 = 32 毫秒,最大值 = 35 毫秒,平均值 = 33 毫秒
-Command
如果我对参数使用单引号而不是双引号,为什么命令字符串只是按原样呈现而不是执行?
解决方案
js2010 的有用答案是正确的,因为使用Start-Process
是您的问题所附带的,并且该行为特定于 PowerShell 的CLI (对于powershell.exe
Windows PowerShell和PowerShell [Core] 6+):pwsh
在 Windows [1]上,需要考虑两层评估:
(a) 将命令行初始解析为参数。
(b)由于使用 ( ) CLI 参数,将(空格连接的)结果参数评估为 PowerShell 代码。
-Command
-c
回复(一):
与 Windows 上的大多数控制台程序一样,PowerShell 仅识别"
字符。(双引号) - 不也是'
(单引号) - 具有句法功能。[2]
也就是说,除非
"
字符。被转义,它们是在解析过程中被删除的字符串分隔符。正如上面所暗示的,
'
字符。不被删除。
无论结果是什么参数 - 一个可能"
被剥离的标记的数组 - 都与它们之间的单个空格连接起来,这成为 (b) 的输入。
为了在您的示例的上下文中解释这一点,请Start-Process
从图片中删除:
注意:以下内容适用于调用自或不涉及 shell 的cmd.exe
任何上下文(包括Start-Process
和 Windows 运行 ( WinKey-R) 对话框)。相比之下,如果需要, PowerShell会在后台重新引用命令行以始终使用 . "
换句话说:以下适用于PowerShell 所见的命令行。
单引号命令:
# Note: This *would* work for calling ping if run from
# (a) PowerShell itself or (b) from a POSIX-like shell such as Bash.
# However, via cmd.exe or any context where *no* shell is involved,
# notably Start-Process and the Windows Run dialog, it does not.
powershell -Command 'ping google.com'
(a) 导致 PowerShell 找到以下两个逐字参数:
'ping
和google.com'
(b) 将这些逐字参数连接到表单
'ping google.com'
[2]并作为 PowerShell 代码执行,因此输出此字符串文字的内容,ping google.com
双引号命令:
powershell -Command "ping google.com"
(a) 导致 PowerShell 剥离句法
"
字符,找到以下单个逐字参数:ping google.com
(b) 然后导致这个逐字参数 -
ping google.com
作为 PowerShell 代码执行,因此导致命令调用,即ping
带有参数的可执行文件google.com
。
[1] 在类 Unix 平台上,第一层不适用,因为被调用的程序只会看到一个逐字参数数组,而不是它们自己必须解析为参数的命令行。并不是说,如果您从类似 POSIX 的 shell(例如在类 Unix 平台上)调用 PowerShell CLI,则该 shell将单引号识别为字符串分隔符,并在PowerShell 看到它们之前将其剥离。bash
[2] 令人惊讶的是,在 Windows 上,最终由每个单独的程序来解释命令行,并且有些程序确实选择将其识别'
为字符串分隔符(例如,Ruby)。但是,Windows 上的许多程序(包括 PowerShell 本身)都基于 C 运行时,它只能识别"
.
[3] 顺便说一句,请注意,这意味着正在发生空白规范化:也就是说,
powershell -Command 'ping google.com'
同样会导致'ping google.com'
.
推荐阅读
- sql - 在下面的内部联接的 oracle 查询中得到错误
- c# - 401 - 使用 OData 和 .Net 连接到 D365 Finance and Operations
- java - Android Studio 中的突然编译错误;错误:找不到符号类 ComputableLiveData
- javascript - 如何从浏览器控制台检索记录的数据到 http 服务器
- wordpress - WordPress Post Meta 而不是自定义帖子类型中的标题
- perl - Perl 有交互式命令行环境吗?
- php - 将十进制数存储到 MySQL 数据库中
- scala - Is parameter evaluation order guraanteed in scala?
- java - 如何在mybatis的IN子句中使用超过1000个args?
- jquery - 用于更改特定文本数据的背景颜色的 Jquery 代码