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[]]
。
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 详细介绍了 (...)
(仅单语句)和 $(...)
(多语句,具有管道逻辑)之间的区别。
我试图了解 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[]]
。
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 详细介绍了 (...)
(仅单语句)和 $(...)
(多语句,具有管道逻辑)之间的区别。