在将PowerShell对象汇总到控制台时动态生成列

时间:2017-11-10 12:26:46

标签: powershell

我有这个PowerShell cmdlet,它返回零个或多个自定义对象;返回的每个对象都有TypeIDStatus属性,因此将cmdlet的输出发送到控制台将导致如下所示:

Type      ID      Status
----      --      ------
Foo       1       Active
Foo       3       Active
Baz       1       Inactive
Baz       2       Active
Baz       3       Broken
Bar       4       Active

使用PowerShell格式化文件,我尝试生成以下输出:

ID    Foo     Baz       Bar
--    ---     ---       ---
1     Active  Inactive  
2             Active
3     Active  Broken
4                       Active

这有可能吗?通过ID对项目进行分组似乎很简单,但我还没有了解如何动态生成每个Type的列?

请注意,我无法对cmdlet的输出类型进行任何更改,因为这会破坏我可能想要输出输出的其他cmdlet - 这就是为什么我认为解决方案理想情况下只涉及格式化。

修改 另一种思考这个问题的方法可能是:"你可以使用PowerShell格式化文件在管道中的最后一个项目被处理后打印一种页脚吗?"我想这假设每个单独项目的处理可以某种方式缓冲该项目,然后可以使用汇总缓冲项目的脚本块构建页脚。

1 个答案:

答案 0 :(得分:1)

PowerShell格式文件不会对您有所帮助。例如,格式文件确定在您运行Get-ChildItemGet-Process时显示哪些字段及其顺序。你在这里做的是动态变换。在SQL中,此操作称为PIVOT。 PIVOT通常是一种痛苦的动态PIVOTs,因为它们从根本上改变了数据。你将不得不手动完成。

那就是说,这并不是很难:

$Data = [PSCustomObject]@{Type = 'Foo'; ID = 1; Status = 'Active'  },
[PSCustomObject]@{Type = 'Foo'; ID = 3; Status = 'Active'  },
[PSCustomObject]@{Type = 'Baz'; ID = 1; Status = 'Inactive'},
[PSCustomObject]@{Type = 'Baz'; ID = 2; Status = 'Active'  },
[PSCustomObject]@{Type = 'Baz'; ID = 3; Status = 'Broken'  },
[PSCustomObject]@{Type = 'Bar'; ID = 4; Status = 'Active'  }

function Get-PivotedObject {
    param (
        [Parameter(Mandatory = $true)]
        $Data,
        [Parameter(Mandatory = $true)]
        [string]$Entity,
        [Parameter(Mandatory = $true)]
        [string]$Attribute,
        [Parameter(Mandatory = $true)]
        [string]$Value
    )

    $PivotHeaders = $Data | Select-Object -ExpandProperty $Attribute -Unique;

    $Data | Select-Object -ExpandProperty $Entity -Unique | ForEach-Object {
        $Record = [ordered]@{
            $Entity = $_;
        }
        foreach ($Header in $PivotHeaders) {
            $Record.$Header = $Data | Where-Object { 
                ($_.$Entity -eq $Record.$Entity) -and ($_.$Attribute -eq $Header)
            } | Select-Object -ExpandProperty $Value -First 1;
            # Notice this only returns the first value it finds for a given entity and attribute

        }

        [PSCustomObject]$Record;
    }
}

Get-PivotedObject -Data $Data -Entity 'ID' -Attribute 'Type' -Value 'Status'