Powershell 在单个命令行上组合变量表达式

Powershell Combining variable expressions on a single command line

我试图了解 Powershell 如何处理命令行上的变量表达式(例如,作为 cmdlet 的参数)。我似乎无法确切地理解它是如何解析涉及多个变量的表达式(变量的 and/or 属性)。下面是一些基于以下预定义变量的示例:

$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)无效——我认为它读起来更清晰。

$()() 之间存在一些细微差别。我会说在你的例子中,在大多数情况下,你应该使用 ()

$() 可以在您需要更复杂的东西或在 () 中不起作用的表达式时使用。请注意 $() 的输出基本上就像是管道的输出,因此会发生一些您可能意想不到的事情。例如看看这两个的输出:

(1..10 -as [string[]]).GetType()
$(1..10 -as [string[]]).GetType()

在第二种情况下,[string[]] 数组被展开,然后重新分组为 PowerShell 的默认数组输出类型 [object[]]

See this GitHub issue for more information about the vagaries of how arguments are treated and parsed when unquoted and ungrouped.

tl;博士:

最安全的选项是始终化合物[=]使用显式双引号 69=] 参数,以便通常的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 主要 将复合参数 视为 双引号(即可扩展)字符串,但是最终 例外情况太多 使此行为变得有用

This GitHub issue 总结了所有令人惊讶的行为。


至于你的具体问题

I can't combine variables with other variable properties (example 4).

实际上,echo $a$f.BaseName是复合标记隐式处理的情况,就好像它被包含在"..."中一样,正是因为您需要将 $f.BaseName 包含在 $(...) 中,因为那是 the string-expansion rules 的要求。

echo $a$($f.BaseName)

I realize I can accomplish this using $() style expressions, like: echo $($a + '\' + $f.BaseName)

其实这种情况下直接使用(...)会更好更高效,因为你要求值的是单个表达式:

echo ($a + '\' + $f.BaseName)

briantist's helpful answer 详细介绍了 (...)(仅单语句)和 $(...)(多语句,具有管道逻辑)之间的区别。