为什么直接调用脚本(在PowerShell控制台或ISE中)或通过另一个PowerShell实例调用脚本时,PowerShell会对引号参数进行不同的处理?
以下是脚本(TestQuotes.ps1
):
param
(
[string]
$Config = $null
)
"Config = $Config"
以下是结果:
PS D:\Scripts> .\TestQuotes.ps1 -Config "A B C"
Config = A B C
PS D:\Scripts> PowerShell .\TestQuotes.ps1 -Config "A B C"
Config = A
PS D:\Scripts> .\TestQuotes.ps1 -Config 'A B C'
Config = A B C
PS D:\Scripts> PowerShell .\TestQuotes.ps1 -Config 'A B C'
Config = A
有什么想法吗?
答案 0 :(得分:6)
根据PowerShell.exe Command-Line Help,powershell
可执行文件的第一个参数为-Command
:
PowerShell[.exe]
[-Command { - | <script-block> [-args <arg-array>]
| <string> [<CommandParameters>] } ]
[-EncodedCommand <Base64EncodedCommand>]
[-ExecutionPolicy <ExecutionPolicy>]
[-File <FilePath> [<Args>]]
[-InputFormat {Text | XML}]
[-Mta]
[-NoExit]
[-NoLogo]
[-NonInteractive]
[-NoProfile]
[-OutputFormat {Text | XML}]
[-PSConsoleFile <FilePath> | -Version <PowerShell version>]
[-Sta]
[-WindowStyle <style>]
PowerShell[.exe] -Help | -? | /?
-Command
之后的任何文本均作为单个命令行发送到PowerShell。...
当
-Command
的值是一个字符串时,Command
必须是指定的最后一个参数,因为在命令后键入的任何字符都将解释为命令参数。>
使用echoargs可以轻松检查子PowerShell实例实际收到的内容:
PS > echoargs .\TestQuotes.ps1 -Config "A B C"
Arg 0 is <.\TestQuotes.ps1>
Arg 1 is <-Config>
Arg 2 is <A B C>
子实例将其进一步解析为:
'.\TestQuotes.ps1' '-Config' 'A' 'B' 'C'
这是您得到“错误”结果的地方:Config = A
如果指定-File
自变量,则将获得所需的结果:
PS > PowerShell -File .\TestQuotes.ps1 -Config 'A B C'
Config = A B C
PS > PowerShell -Command .\TestQuotes.ps1 -Config 'A B C'
Config = A
答案 1 :(得分:4)
tl; dr
如果您从PowerShell 调用另一个PowerShell实例,请使用脚本块({ ... }
)以获得可预测的行为:
Windows PowerShell:
powershell.exe { .\TestQuotes.ps1 -Config "A B C" }
PowerShell 核心:
pwsh { .\TestQuotes.ps1 -Config "A B C" }
此将使参数的引用按预期工作-甚至从调用中返回具有近似保真度的 objects ,因为序列化与用于使用了PowerShell远程处理。
但是请注意,从PowerShell的外部 (例如cmd.exe
或 )调用时,这不是 不是 bash
。
请继续阅读,以了解您在脚本块的缺少中看到的行为。
PowerShell CLI (调用powershell.exe
(Windows PowerShell)/ pwsh.exe
(PowerShell Core ))仅支持一个参数,该参数接受 positional 参数(即,没有以参数名称开头的值,例如-Command
)。
在 Windows PowerShell中,(隐含)参数为 -Command
。
在 PowerShell Core 中,它是 -File
。
第一个位置参数(如果有)后的 中的任何参数将被考虑:
在Windows PowerShell中: PowerShell源代码片段的一部分传递给了(暗示)
-Command
参数。
:各个参数传递给作为文字传递给脚本文件 第一个位置参数(隐含的-File
参数)。
传递给-Command
的参数-无论是隐式还是显式-由PowerShell进行两次 次解析,这可能很棘手:
在第一轮轮中,将包围单个参数的"..."
(双引号)剥去。
'...'
括起来(单引号)的参数,因为场景,PowerShell 重新引用这样的参数,以便在调用外部程序(包括PowerShell CLI本身)时使用"..."
。在第二回合中,将剥离的参数加上空格,形成单个字符串,然后 解释为 PowerShell源代码。
应用于您的调用,这意味着两者 PowerShell .\TestQuotes.ps1 -Config "A B C"
和PowerShell .\TestQuotes.ps1 -Config 'A B C'
都导致PowerShell最终解析并执行以下代码:
.\TestQuotes.ps1 -Config A B C
也就是说,由于进行了两轮解析,原始报价被丢失,导致传递了三个个不同的参数,解释您的症状。
如果必须在没有脚本块的情况下使命令工作 ,则有两个选择:
使用-File
,仅应用一个一轮解析:
powershell.exe -File .\TestQuotes.ps1 -Config "A B C"
"..."
之外,生成的参数还被视为 literals -然而,通常是 您想要的。 使用(暗示)-Command
,应用额外的报价层 :
powershell.exe -Command .\TestQuotes.ps1 -Config '\"A B C\"'
请注意PowerShell如何要求"
个字符。要在传递给其CLI的参数中以\"
的形式转义,而在PowerShell中的 中必须使用`"
(或""
)