gpt4 book ai didi

powershell - 如果不分配给变量,为什么 Powershell Array of Array 显示不同的内容

转载 作者:行者123 更新时间:2023-12-02 23:53:02 25 4
gpt4 key购买 nike

如果 cmdlet 返回数组数组,例如:

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

while 赋值给一个变量:
$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
}
test的输出:
key1  
----
value1
value1
value1

最佳答案

PetSerAl 在一个简短的评论中提供了关键的指针:

输出渲染 的 差异归结为以下事实:

  • 语句 test 是命令 (调用函数、cmdlet 或外部程序)
  • $result(之前捕获了 test 的输出)是一个表达式 (只涉及变量引用、PowerShell 的运算符和 .NET 方法调用,尽管它可能包含嵌套的管道 - )。

  • 通过从 , $results.ToArray() 函数(函数是命令的一种形式)输出 test,您正在使用 , 数组构造运算符将 $results.ToArray()(导致数组数组)包装在一个辅助数组中,临时数组,这是确保集合作为单个对象传递而不是枚举其元素的常用技术。

    辅助。包装器数组 是:
  • 在输出到管道 时总是丢失,由于管道的自动展开(展开)行为,
  • 但它 确保包装的数组被管道 中的下一个命令视为单个对象。
  • , $results.ToArray() 在你的函数中概念上更清晰但更冗长的等价物是 Write-Output -NoEnumerate $results.ToArray() ;也就是说,PowerShell 的通常隐式输出是显式的,请求抑制枚举输出集合的默认行为。

    鉴于管道中没有其他命令,tests 输出被隐式打印到屏幕上。
    在手头的情况下,将数组数组作为单个对象打印会导致您看到的属性列表输出格式。

    相比之下, $result ,由于是一个表达式,隐式枚举为 。也就是说,从 test 捕获的数组数组 - 没有辅助。包装阵列! - 一次将一个元素发送到输出格式系统,然后这些元素会更有意义地呈现。

    提供一个 更简单的例子 :

    假设您的函数 test 使用 return , , (1..3) 来输出包含最终包含在辅助中的 3 元素数组的容器数组。单元素数组(顺便说一句:PowerShell 中的 return 只是退出函数或脚本块的语法糖,它与输出内容没有直接关系)。

    执行 test 函数相当于直接执行以下表达式:
    , , (1..3)

    即,外,辅助。由于隐式枚举,数组再次被丢弃,并且 , (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)

    即,外,辅助。数组在 $result = test 期间丢失,容器数组现在也被隐式枚举,并且 (1..3) 作为单个对象呈现更有意义(您无法在视觉上将其与将 1..3 直接发送到管道(即逐个元素)区别开来):
    1
    2
    3

    如何格式化数组以供显示

    当命令或表达式既没有在变量中捕获,也没有发送到管道到另一个命令,也没有重定向(使用 >>> )时,它会使用 PowerShell 的默认输出格式系统隐式打印到屏幕(主机)。

    你可以想到一个命令,例如:
    test

    相当于[1]:
    test | Out-Host
    Out-Host 根据第一个输入对象,自动选择一个 Format-* cmdlet 用于渲染,适合手头的输入:
    如果该对象具有 4 个或更少的属性,则选择 Format-Table;否则,它是 Format-List

    但是,如果第一个输入对象是一个集合(实现 IEnumerable ),则格式化 cmdlet 的选择所基于的就是该集合的第一个元素(与整个集合类型相反),并且集合的元素使用单独格式化那个 cmdlet。

    $result 变量获取输出的情况下,输入数组的第一个元素是 [pscustomobject] 实例(使用 New-Object PSObject 创建),具有 1 个属性 key1 ;因此,选择了 Format-Table,并且构成数组的 [pscustomobject]` 实例以表格格式显示。

    相比之下,在您调用 test 的情况下,输入数组的第一个元素是另一个数组,它本身没有进一步枚举。 Get-Member -InputObject (1,2) -Type Property揭示了一个阵列具有8种性质(CountIsFixedSizeIsReadOnlyIsSynchronizedLengthLongLengthRankSyncRoot),这就是为什么Format-List被选择,列出每个属性作为单独的行的名称/值对。

    当然,您可以选择显式使用格式化 cmdlet,PetSerAl 指出格式化 cmdlet 支持 -Expand 参数,这使您可以控制作为集合的输入对象的格式化方式:您可以要求枚举集合,即, 打印其元素( -Expand EnumOnly ,这是默认值),仅显示集合自己的属性,而不打印其元素( -Expand CoreOnly ),或两者( -Expand Both )。

    但是请注意,您不能通过 -Expand 请求额外的枚举级别,因此您的 test 输出不能直接格式化以显示嵌套数组的各个元素。
    但是,通过管道传递到 Write-Output 来实现这一点是微不足道的,它执行单独呈现元素所需的额外枚举级别:
    test | Write-Output

    [1] 更准确地说,正如 PetSerAl 指出的那样,它是: . { test } 2>&1 | Out-Default ,使用户能够覆盖 Out-Default cmdlet 以进行自定义格式设置。

    关于powershell - 如果不分配给变量,为什么 Powershell Array of Array 显示不同的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54159779/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com