如果未分配给变量,为什么数组的Powershell数组显示不同的内容
如果cmdlet返回数组的数组,例如:如果未分配给变量,为什么数组的Powershell数组显示不同的内容,powershell,Powershell,如果cmdlet返回数组的数组,例如: function test() { $results = New-Object System.Collections.ArrayList $array = @() for ($idx = 0; $idx -lt 3; $idx++) { $obj = New-Object PSObject -Property @{ "key1" = "value1"; }
function test() {
$results = New-Object System.Collections.ArrayList
$array = @()
for ($idx = 0; $idx -lt 3; $idx++) {
$obj = New-Object PSObject -Property @{
"key1" = "value1";
}
$array += @($obj)
}
[Void] $results.add($array)
return ,$results.TOArray()
}
那么,当指定返回值时,输出是不同的
如果直接运行test
,则显示:
test
Length : 3
LongLength : 3
Rank : 1
SyncRoot : {@{key1=value1}, @{key1=value1}, @{key1=value1}}
IsReadOnly : False
IsFixedSize : True
IsSynchronized : False
Count : 3
分配给变量时:
$result = test
$result
key1
----
value1
value1
value1
如果cmdlet返回一个一级数组,则test
和$(test)
的输出是相同的
function test() {
$array = New-Object System.Collections.ArrayList
for ($idx = 0; $idx -lt 3; $idx++) {
$obj = New-Object PSObject -Property @{
"key1" = "value1";
}
$array += @($obj)
}
return ,$array
}
测试
的输出:
key1
----
value1
value1
value1
在简短的评论中提供了关键的指针:
输出渲染的差异可归结为以下事实:
- 语句
是一个命令(对函数、cmdlet或外部程序的调用)test
- 而
(之前捕获了$result
测试的输出)是一个表达式(只涉及变量引用、PowerShell运算符和.NET方法调用,在管道外部-尽管它可能包含嵌套命令)
test
函数(函数是命令的一种形式)输出,$results.ToArray()
,您使用数组构造运算符,
,将$results.ToArray()
(生成数组数组)包装到辅助的临时单元素数组中,这是确保集合作为单个对象传递而不是枚举其元素的常用技术
也就是说,辅助系统。包装器数组是:
- 由于管道的自动展开(展开)行为,输出到管道时总是丢失
- 但它确保管道中的下一个命令将包装的数组视为单个对象
,$results.ToArray()
在概念上更清晰,但更详细的等价物是写输出-NoEnumerate$results.ToArray()
;也就是说,PowerShell通常隐式的输出是显式的,请求抑制枚举输出集合的默认行为
假定管道中没有其他命令,tests
输出隐式打印到屏幕上。
在本例中,将数组数组作为单个对象打印会导致您看到的属性列表输出格式
相比之下,$result
,由于是表达式,因此隐式枚举。也就是说,从test
-捕获的阵列阵列不带aux。包装器数组!-一次发送一个元素到输出格式系统,然后这些元素呈现得更有意义
要提供一个更简单的示例,请执行以下操作: 假设您的函数
test
使用return,(1..3)
输出一个容器数组,其中包含一个最终封装在aux中的3元素数组。单元素数组(作为旁白:return
在PowerShell中只是用于退出函数或脚本块的语法糖,它与输出没有直接关系)
执行test
函数相当于直接执行以下表达式:
也就是说,外部,aux。由于隐式枚举,数组再次被丢弃,,(1..3)
被呈现为单个对象,导致属性列表格式:
Length : 3
LongLength : 3
Rank : 1
SyncRoot : {1, 2, 3}
IsReadOnly : False
IsFixedSize : True
IsSynchronized : False
Count : 3
相比之下,执行$result
(在运行$result=test
之后)相当于:
, (1..3)
也就是说,外部,aux。数组在$result=test
过程中丢失,容器数组现在也隐式枚举,并且(1..3)
作为单个对象呈现更具意义(您无法从视觉上区分它是否直接将1..3
发送到管道,即逐个元素):
数组的显示格式 如果命令或表达式既没有在变量中捕获,也没有发送到管道到另一个命令,也没有重定向(使用
或>
),则使用PowerShell的默认输出格式系统将其隐式打印到屏幕(主机)
您可以考虑以下命令:
test
等同于[1]:
Out Host
根据第一个输入对象,自动选择一个格式-*
cmdlet用于呈现适合当前输入的内容:
如果该对象具有4个或更少的属性,则选择格式表
;否则,它是格式列表
但是,如果第一个输入对象是一个集合(实现IEnumerable
),则选择格式化cmdlet所基于的是该集合的第一个元素(而不是整个集合类型),并且使用该cmdlet分别格式化集合的元素
在$result
变量获得输出的情况下,输入数组的第一个元素是[pscustomobject]
实例(使用新对象PSObject
创建),具有1个属性,键1
;因此,选择了Format Table
,组成数组的[pscustomobject]`实例以表格格式显示
相反,在test
调用的情况下,输入数组的第一个元素是另一个数组,它本身没有进一步枚举<代码>获取成员-输入对象(1,2)-类型属性显示数组有8个属性(计数
,是固定大小
,是只读的
,是同步的
,长度
,秩
,同步根
),这就是为什么选择了格式列表
,将每个属性作为名称/值对列在其自己的行中
当然,您可以选择显式使用格式化cmdlet,PetSerAl指出,格式化cmdlet支持-Expand
参数,这使您可以控制
1
2
3
test
test | Out-Host
test | Write-Output