Ale*_*vis 2 windows parameters quotes powershell
当直接(在PowerShell控制台或ISE中)调用脚本或通过另一个PowerShell实例调用脚本时,为什么PowerShell会对引号参数进行不同的处理?
这是脚本(TestQuotes.ps1):
param
(
[string]
$Config = $null
)
"Config = $Config"
Run Code Online (Sandbox Code Playgroud)
结果如下:
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
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
根据PowerShell.exe命令行帮助,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 | -? | /?
Run Code Online (Sandbox Code Playgroud)
之后的所有文本
-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>
Run Code Online (Sandbox Code Playgroud)
子实例进一步将其解析为:
'.\TestQuotes.ps1' '-Config' 'A' 'B' 'C'
Run Code Online (Sandbox Code Playgroud)
这是您得到“错误”结果的地方: 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
Run Code Online (Sandbox Code Playgroud)
太长了;博士
如果您从 PowerShell调用另一个 PowerShell 实例,请使用脚本块( ){ ... }来获得可预测的行为:
Windows PowerShell:
# To pass arguments to the script block, append -args ...
powershell.exe { .\TestQuotes.ps1 -Config "A B C" }
Run Code Online (Sandbox Code Playgroud)
PowerShell核心:
# To pass arguments to the script block, append -args ...
pwsh { .\TestQuotes.ps1 -Config "A B C" }
Run Code Online (Sandbox Code Playgroud)
这将使参数的引用按预期工作- 它甚至会从调用中返回具有接近类型保真度的对象,因为采用了类似于 PowerShell 远程处理所使用的序列化。
但请注意,当从PowerShell外部(例如来自或 )调用时,这不是一个选项。cmd.exebash
请继续阅读,了解在没有脚本块的情况下您所看到的行为的解释。
PowerShell CLI(调用powershell.exe(Windows PowerShell) / pwsh.exe(PowerShell Core )仅支持一个接受位置参数的参数(即前面没有参数名称的值,例如-Command)。
在Windows PowerShell 中,该(隐含)参数是-Command。
在PowerShell Core中,它是-File。
第一个位置参数之后的任何参数(如果有)都会被考虑:
在 Windows PowerShell 中:传递给(隐含)参数的 PowerShell 源代码片段的一部分-Command。
在 PowerShell Core中:作为文字传递到第一个位置参数(隐含参数)中指定的脚本文件的各个参数。-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
Run Code Online (Sandbox Code Playgroud)
也就是说,由于两轮解析,原始引用丢失了,导致传递了三个不同的参数,这解释了您的症状。
如果您必须让命令在没有脚本块的情况下工作,您有两个选择:
Use-File,仅应用一轮解析:
powershell.exe -File .\TestQuotes.ps1 -Config "A B C"
Run Code Online (Sandbox Code Playgroud)
"...",结果参数还被视为文字- 然而,这通常是您想要的。使用 (implied) -Command,应用额外的引用层:
powershell.exe -Command .\TestQuotes.ps1 -Config "'A B C'"
Run Code Online (Sandbox Code Playgroud)
外部"..."在命令行解析期间被剥离,留下内部的单引号'A B C'字符串作为要执行的代码的一部分。
如果您也想使用"内部引用(此处不需要),则必须"\"A B C\""从PowerShell外部使用并从PowerShell内部使用"\`"A B C\`""[1] - 也就是说,PowerShell 需要字符。在传递给 CLI 的参数中进行转义,而在 PowerShell 中,必须使用(或)。"\"`"""
[1]\转义应该不是`必需的,但不幸的是,这是由于至少在 PowerShell 7.2.x 之前存在的长期错误,该错误可能会在 7.3 中得到修复 - 请参阅此答案
| 归档时间: |
|
| 查看次数: |
337 次 |
| 最近记录: |