为什么当您直接调用脚本(在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
有什么主意吗?
2条答案
按热度按时间waxmsbnn1#
根据PowerShell.exe Command-Line Help,
powershell
可执行文件的第一个参数是-Command
:-Command
之后的任何文本都将作为单个命令行发送到PowerShell。..。
当
-Command
的值是字符串时,Command
必须是指定的最后一个参数,因为命令后键入的任何字符都被解释为命令参数。使用echoargs可以很容易地查看PowerShell子示例实际收到的内容:
子示例进一步将其解析为:
这就是您得到“错误”结果的地方:
Config = A
如果指定
-File
参数,您将获得所需的结果:tsm1rwdh2#
tl;dr
如果您要**从PowerShell调用另一个PowerShell示例,请使用脚本块(
{ ... }
)**来获得可预测的行为:Windows PowerShell:
PowerShell酷睿:
这将使参数引用按预期工作--它甚至将从调用中以接近类型的保真度返回对象,因为使用了类似于PowerShell远程处理的序列化。
但是,请注意,当从PowerShell的外部**调用时,例如从
cmd.exe
或bash
,这不是*选项。请继续阅读,了解在没有脚本块的情况下看到的行为的解释。
PowerShell CLI(调用
powershell.exe
(Windows PowerShell)/pwsh.exe
(PowerShellCore)仅支持一个接受位置*参数的参数(即前面没有参数名称*的值,如-Command
))。-Command
。-File
**。-Command
参数。-File
参数)中指定的脚本文件。传递给
-Command
的参数--无论是隐式的还是显式的--都要经过PowerShell的*两轮解析**,这可能很棘手:"..."
(双引号)被剥离。'...'
括起来(单引号)的参数,因为PowerShell在幕后重新引号此类参数,以便在调用外部程序(包括PowerShell CLI本身)时使用"..."
。应用于您的调用,这意味着*
PowerShell .\TestQuotes.ps1 -Config "A B C"
和PowerShell .\TestQuotes.ps1 -Config 'A B C'
都导致PowerShell最终解析并执行以下代码:也就是说,由于两轮解析,原来的引用丢失了,导致三个不同的参数被传递,这就解释了您的症状。
如果您必须让您的命令在没有*脚本块**的情况下工作,您有两个选择:
-File
,只进行一轮解析:"..."
之外,生成的参数被视为文字--然而,这通常是您想要的。-Command
,增加引号:外部的
"..."
在命令行解析期间被剥离,留下内部的单引号'A B C'
字符串作为要执行的代码的一部分。如果您还想将
"
用于内部引用(这里不是必需的),则必须使用来自外部PowerShell的"\"A B C\""
和来自内部PowerShell的"\
"A B C`""[1]-也就是说,PowerShell需要
"个字符。要在*传递给其CLI*的参数中将
"转义为
",而在*PowerShell*中,必须使用``"
(或""
)。[1]除了```之外,
\
的转义应该不是必须的,但不幸的是,这是由于至少是PowerShell 7.2.x的一个长期存在的错误所致,该错误可能在7.3中得到修复-请参阅this answer