1. 问题
在powershell中,有时,我们会需要向之前的一个数组中添加更多的元素,如果是添加单个对象,只需要使用操作符+=
。但我们要合并两个多对象的数组时,需要通过遍历来将一个数组添加到另一个数组之中,这一过程是相当繁琐的。当然也可以使用List
或ArrayList
对象中的AddRange
方法,但也需要进行类型转化。有没有更简洁的方式来合并两个甚至更多的数组呢?
2. 解决方案
powershell是直接输出对象,遍历对象数组(可关闭)。在数组的处理上,如果要使用到索引,建议使用强类型进行约束。另一方面,如果要合并数组,不必手动遍历,直接使用
$(;)
将多行输出结果合并赋值即可。
powershell中可以将各种表达式的输出结果可以使用用$()
或&{}
汇总赋值给某一变量。Write-Output
(别名echo
)的帮助文档表明1,其作用是将指定对象输出到控制台或管道中,默认遍历数组。当然也可以启用-NoEnumerate
开关参数来将整个数组传递给管道。该命令使用的是Cmdlet.WriteObject(object sendToPipeline, bool enumerateCollection)
2方法。
创建数组主要使用@()
和,
。使用$(;)
可以实现数组的合并,还可以搭配Write-Output
选择是否遍历数组。下面代码中可以看出,虽然输出结果看似一致,但其结构是不一样的。因为无论数组嵌套了多少层,最终都会被递归为深度为一的数组。
$arr1 = [pscustomobject]@{
FullName = "C:\temp"; Name = "temp" }
# FullName Name
# -------- ----
# C:\temp temp
$arr2 = 1..3 | % {
[pscustomobject]@{
FullName = "C:\temp\file_$_"} }
# FullName
# --------
# C:\temp\file_1
# C:\temp\file_2
# C:\temp\file_3
$arr3 = @($arr1, $arr2) # 创建一个长度为2的数组
$arr3 = $arr1, $arr2 # 省略后的数组生成方式
$arr3 = $(echo $arr1 -NoEnumerate; echo $arr2 -NoEnumerate)
# 上式结果与前面的数组生成、使用+=操作符结果相一致
$arr4 = $($arr1; $arr2)
# 将echo枚举结果合并,赋值给新变量
# 该结果长度为4,$arr1 和 $arr2 都被 echo 所遍历
# 类似动态规划枚举节点树
另一方面,由于WriteObject()
会将长度为1的数组遍历为内部的对象,因此在数组经过管道或函数生成数组类型的值时,若想保持数组的完整性,需要在赋值时使用强类型进行约束。例如Get-Content
等大多数命令结果都为数组,遇到单行文本时,使用索引取值就会出问题。不过管道与foreach并不会遇到这样的问题,可以放心使用。
$arr5 = @(1) | %{
"line 1" }; $arr5.pstypenames
# System.String
# System.Object
# 使用强类型约束,[array]可以换为[<classType>[]]的形式
$arr5 = [array](@(1) | %{
"line 1" })
[array]$arr5 = (@(1) | %{
"line 1" })