我试图理解Powershell如何在命令行上处理变量表达式(例如,作为cmdlet的参数)。我似乎无法准确理解它如何解析涉及多个变量(和/或变量属性)的表达式。以下是基于以下预定义变量的示例:
$a = 'abc'
$b = 'def'
$f = Get-ChildItem .\Test.txt # assuming such a file exists in the current directory
示例1:
echo $a$b
输出:abcdef
示例2:
echo $a\$b
输出:abc\def
示例3:
echo $f.BaseName
输出:Test
示例4:
echo $a\$f.BaseName
输出:abc\C:\Test.txt.BaseName
基本上,我不明白为什么我可以组合两个变量(例1和2),我可以使用变量属性(例3),但我不能将变量与其他变量属性组合(例4)。我尝试了各种转义序列(使用反引号)无济于事。
我意识到我可以使用$()
样式表达式完成此操作,例如:
echo $($a + '\' + $f.BaseName)
我只是不明白为什么另一种形式(例子4)无效 - 在我看来它更清晰。
答案 0 :(得分:2)
$()
和()
之间存在一些细微差别。我会说在你的例子中,在大多数情况下,你应该使用()
。
$()
中使用的表达时,可以使用 ()
。请注意,$()
的输出基本上类似于输出管道,所以有些事情可能会发生。例如,看看这两个的输出:
(1..10 -as [string[]]).GetType()
$(1..10 -as [string[]]).GetType()
在第二种情况下,[string[]]
数组已展开,然后重新分组为PowerShell的默认数组输出类型[object[]]
。
答案 1 :(得分:2)
<强> TL; DR:强>
最安全的选项始终对复合参数使用显式双引号,以便<强>通常string expansion (interpolation) rules申请。
应用于您的示例(我正在使用Write-Output
,因为echo
是PowerShell中的别名):
Write-Output "$a$b" # example 1
Write-Output "$a\$b" # example 2
Write-Output "$a\$($f.BaseName)" # example 4 - note the required $(...)
唯一的例外是示例3,因为您没有处理复合参数,而是单个表达式:
Write-Output $f.BaseName # example 3: OK without quoting
Write-Output "$($f.BaseName)" # equivalent with double-quoting
PowerShell 主要是将复合参数视为双引号(即可扩展)字符串,但最终太多异常< / em>此行为有用。
This GitHub issue总结了所有令人惊讶的行为。
至于您的具体问题:
我无法将变量与其他变量属性组合在一起(例4)。
实际上,echo $a\$f.BaseName
是一个复合令牌 被隐式处理的情况,好像它被包含在"..."
中一样,正是因为你需要将$f.BaseName
括在$(...)
中,因为这是the string-expansion rules所需要的。
echo $a\$($f.BaseName)
我意识到我可以使用
$()
样式表达式完成此操作,例如:echo $($a + '\' + $f.BaseName)
实际上,在这种情况下简单地使用(...)
会更好,更有效,因为您要评估的是单个表达式:
echo ($a + '\' + $f.BaseName)
briantist's helpful answer更多地关注(...)
(仅限单一语句)和$(...)
(使用管道逻辑的多个语句)之间的区别。