Powershell - 具有多个属性的组对象 PSObject

Chr*_*uez 1 powershell

我正在尝试获取类似于以下内容的 PSObject 数组

 @{BakId=27; Name=DB_A; Lsn=123; File=A_01; Size=987}
 @{BakId=28; Name=DB_B; Lsn=456; File=B_01; Size=876}
 @{BakId=28; Name=DB_B; Lsn=456; File=B_02; Size=765}
 @{BakId=28; Name=DB_B; Lsn=456; File=B_03; Size=654}
Run Code Online (Sandbox Code Playgroud)

并创建一个新的分组对象,删除冗余的标头信息。

 BakId  Lsn  Name  Files
 27     123  DB_A  {@{File=A_01.bak;Size=777}}
 28     456  DB_B  {@{File=B_01.bak;Size=888}, @{File=B_02.bak;Size=999}, ...}
Run Code Online (Sandbox Code Playgroud)

我尝试使用组对象,但只能让它适用于一个属性。(所有分组属性都以逗号分隔值的字符串形式进入 Group.Name。)

这是我想到的最好的,但感觉很老套。

$list | Group-Object -Property BakId | % {
   $BakId = $_.Name
   $Lsn   = $_.Group[0].Lsn  # <--- is there a better way than this?
   $Name  = $_.Group[0].Name # <--- Ditto
   $Files = $_.Group | Select-Object -Property SequenceNumber, Size
   Write-Output (New-Object -TypeName PSObject -Property @{ BakId=$BakId;Files = $Files })
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的办法?

谢谢

mkl*_*nt0 6

您可以通过使用Select-Object具有计算属性的单个调用来简化构造输出对象的方法,并且根据分组属性的顺序,通过集合访问其特定于组的值.Values

$list | Group-Object -Property BakId, Lsn, Name | 
  Select-Object @{n='BakId'; e={ $_.Values[0] }}, 
                @{n='Lsn';   e={ $_.Values[1] }},
                @{n='Name';  e={ $_.Values[2] }},
                @{n='Files'; e={ $_.Group | Select-Object File, Size }}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • $_.Values[<ndx>]取代$_.Group[0].<name>你的方法;请注意,后者仅对实际分组属性有意义,因为任何其他属性在整个组中都不会是统一的。

  • 从(实例)输出的每个组对象上的集合.Values()按指定的顺序按原样(原始类型)包含该组的共享分组属性值。 相比之下,属性包含所有分组属性值的字符串化组合:包含逗号分隔列表的字符串。 不幸的是,目前缺少此类详细信息。[System.Collections.ArrayList]Group-Object[Microsoft.PowerShell.Commands.GroupInfo]
    .Name
    Get-Help Group-Object


如果您想避免重复分组属性(例如,准备编写函数包装器;PSv3+):

$props = 'BakId', 'Lsn', 'Name'
$list | Group-Object -Property $props | ForEach-Object {
   $propDefs = [ordered] @{}
   foreach ($i in 0..($props.Length-1)) { $propDefs.[$props[$i]] = $_.Values[$i] }
   $propDefs.Files = $_.Group | Select-Object File, Size
   New-Object PSCustomObject -Property $propDefs
}
Run Code Online (Sandbox Code Playgroud)