【问题标题】:Summary tables from multiple tables using Powershell使用 Powershell 来自多个表的汇总表
【发布时间】:2020-06-12 19:06:23
【问题描述】:

所有, 我正在尝试为以下任务编写脚本。 我有多个物理实体,标题为 Entity1Entity2 等。 每个实体都有 CSV 表,其中包含该特定实体的各种子系统的设置。像这样:

SubsystemName   Subsystem code   Execution   Trigger   Period   Last ON
SubSys1         ad1              ON          Timed     1d       01/05/2020  
SubSys2         ad2              OFF         Timed     5d       02/01/2020
SubSys3         af5              ON          Manual    2d       04/02/2020
SubSys4         af5b             OFF         Timed     1d       01/01/2020

我需要做的是形成许多报告/表格,每个报告/表格汇总每个实体的每个子系统的特定设置,例如,查看每个实体的每个子系统的执行是否为 ON 我需要这种表格:

SubSystem Name  Entity1   Entity2   Entity3   Entity4   Entity5
SubSys1         ON        OFF       ON        OFF       OFF          
SubSys2         ON        OFF       ON        ON        OFF
SubSys3         OFF       ON        ON        OFF       OFF
SubSys4         ON        OFF       ON        OFF       OFF
SubSys5         ON        OFF       ON        OFF       OFF

到目前为止我所拥有的: 我清理了 CSV,并将它们写入每个实体的 JSON 文件中,如下所示:Entity1_Scheduler.json 我可能需要对任意一组实体的设置进行审核。由于在文件本身中没有提到这个特定的 JSON 属于什么实体,并且知道文件名的唯一方法是,我读取了一个对象中的每个 JSON,然后我创建了一个带有 NoteProperties 的 PSObject,其中 @987654326 @ - 实体名称和Value = JSONObj JSON 中的所有数据,如下所示:

$myEntities = @{'Entity1', 'Entity2'} #These are the entities I want to audit this time
$myData = [PSObject]::new() #This is going to be object holding all the data

#Reading only files for entities I need and only pick JSON version of it
Get-Content -path ($Path + "\*") -include ($myEntities|%{$_ + "*"}) -filter *.json -Raw | %{
   $currentEntity = ($_.PSChildName -Split "_")[0] #Getting Entity name from file name

   #This is the data for this entity
   $currentJson = ConvertFrom-Json $_

   #Assembling data from all entities in one object
   $myData| Add-Member -MemberType NoteProperty -Name $currentEntity -Value $currentJson
   }

所以,我有一个 PSObject,每个实体都有一个 NoteProperty 成员,其中 Name 是实体名称,Value 是来自帖子第一个表的 JSON 数据。 这就是我卡住的地方。 如何为选定的属性(又名“汇总表”又名“审计报告”)构建表格,在此示例中,执行:

SubSystem Name  Entity1   Entity2   Entity3   Entity4   Entity5
SubSys1         ON        OFF       ON        OFF       OFF          
SubSys2         ON        OFF       ON        ON        OFF
SubSys3         OFF       ON        ON        OFF       OFF
SubSys4         ON        OFF       ON        OFF       OFF
SubSys5         ON        OFF       ON        OFF       OFF

我现在组织数据的方式可以轻松完成吗?还是我应该从一开始就做不同的事情?

注意:并非所有实体都具有所有相同的子系统,因此它应该是所有可能子系统的联合(或完全外连接),对于没有特定子系统的实体,它只是在汇总表中有一些占位符符号,如“NA”或“---”。

【问题讨论】:

    标签: json powershell csv summary psobject


    【解决方案1】:

    如果每个实体数据都存储在自己的 CSV 文件中,例如Entity1.csvEntity2.csvEntity3.csv等,你可以这样做:

    $CSVData = Get-ChildItem -Path C:\EntityFolder -Filter 'Entity*.csv' | Foreach-Object {
        # Add Entity column to CSV data with name of Entity
        Import-Csv -Path $_.FullName | Add-Member -MemberType NoteProperty -Name Entity -Value $_.BaseName -PassThru
    }
    # Get all unique entities
    $Entities = $CSVData.Entity | Select-Object -Unique
    # Using group-object to process each subsystemname at a time
    foreach ($group in $CSVData | Group-Object SubsystemName) {
        $Props = [ordered]@{SubsystemName = $group.Name}
        $Entities | Foreach-Object {
            $Entity = $_
            # Get Execution value for the current entity. It could be null, which is OFF
            $Execution = ($group.Group | Where {$_.Entity -eq $Entity}).Execution
            # Remove if statement and replace with just $execution if null (empty) values are fine
            $Props.Add($Entity,$(if ($Execution) { $Execution } else { 'OFF' }))
        }
        [pscustomobject]$Props
    }
    

    你可以把它变成一个函数,这样你就可以改变为你的摘要选择的列/参数:

    function Get-SummaryTable {
        param($CSVPath,$Parameter)
    
        $CSVData = Get-ChildItem -Path $CSVPath -Filter 'Entity*.csv' | Foreach-Object {
            Import-Csv -Path $_.FullName | Add-Member -MemberType NoteProperty -Name Entity -Value $_.BaseName -PassThru
        }
        $Entities = $CSVData.Entity | Select-Object -Unique
        foreach ($group in $CSVData | Group-Object SubsystemName) {
        $Props = [ordered]@{SubsystemName = $group.Name}
        $Entities | Foreach-Object {
            $Entity = $_
            $Target = ($group.Group | Where {$_.Entity -eq $Entity}).$Parameter
            $Props.Add($Entity,$Target)
        }
        [pscustomobject]$Props
    }
    }
    

    要执行,只需使用适当的参数运行函数:

    Get-SummaryTable 'C:\EntityPath' Trigger
    
    SubsystemName Entity1 Entity2 Entity3
    ------------- ------- ------- -------
    SubSys1       Timed   Timed
    SubSys2       Timed
    SubSys3       Manual  Timed   Timed
    SubSys4       Timed   Manual  Timed
    SubSys5               Timed   Manual
    SubSys6                       Timed
    
    Get-SummaryTable 'C:\EntityPath' Execution
    
    SubsystemName Entity1 Entity2 Entity3
    ------------- ------- ------- -------
    SubSys1       ON      OFF
    SubSys2       OFF
    SubSys3       ON      OFF     ON
    SubSys4       OFF     OFF     ON
    SubSys5               OFF     ON
    SubSys6                       ON
    

    【讨论】:

    • 好的,所以您将使用 PSObject 数组,将实体添加为列。正如我在帖子中展示的那样,我最初选择使用由 Name = Entity 和 Value = (CSVdata/JSON for each tool) 组成的 PSObject,因为添加另一个填充有实体名称的列似乎不够优雅。让我退后一步,按照你的方式尝试。
    • 还有一个问题。我没有在我的示例列中显示它,但在 Subsystemname 列旁边有 subsystemDescription 列。名称不是很有描述性,用户可能不明白它的含义,但它是独一无二的,描述是描述性的,但不是唯一的(即许多项目,如“未使用此子系统”)。我需要将它包含在报告中的子系统名称列旁边。有什么方法可以在你的代码中做到这一点,或者我需要在外面创建一个字典并使用它?
    • 好吧,你写的脚本我得到的输出很奇怪:它有两列,名称和值,名称有:SubsystemName, Entity1, Entity2, Entity3,SubsystemName, Entity1, Entity2 、Entity3 等。值列具有以下内容:Subsystem1、ON、OFF、Subsystem2、ON、ON 等。
    • 正常输出它的唯一方法是:将你的$Props(只有一行)收集到数组 $PropsArray 中,这样:$PropsArra | Select-Object @{Label = "SubsystemName"; Expression={$_.subsystemname}}, @{Label = "Entity1"; Expression = {$_.Entity1}} 等等。问题是我不知道如何动态形成这种语法,每次都有各种实体
    【解决方案2】:

    您应该能够使用 Format-Table 来获得所需的结果。 我在这里做了一个小例子,这样你就可以看到这个方法,看看这是否适合你的目的。

    #Setting up new generic objects
    $object1 = New-Object PSCustomObject
    $object2 = New-Object PSCustomObject
    $object3 = New-Object PSCustomObject
    
    #Adding noteproperties to each object, so they have different properties
    $object1 | Add-Member -MemberType NoteProperty -Name 'Entity1' -Value 'ON'
    $object1 | Add-Member -MemberType NoteProperty -Name 'Entity2' -Value 'ON'
    $object1 | Add-Member -MemberType NoteProperty -Name 'Entity3' -Value 'OFF'
    $object2 | Add-Member -MemberType NoteProperty -Name 'Entity1' -Value 'OFF'
    $object2 | Add-Member -MemberType NoteProperty -Name 'Entity2' -Value 'ON'
    $object2 | Add-Member -MemberType NoteProperty -Name 'Entity4' -Value 'ON'
    $object3 | Add-Member -MemberType NoteProperty -Name 'Entity2' -Value 'ON'
    $object3 | Add-Member -MemberType NoteProperty -Name 'Entity3' -Value 'OFF'
    $object3 | Add-Member -MemberType NoteProperty -Name 'Entity4' -Value 'ON'
    
    #Manual setup of header fields, this could be populated during information gathering
    $headers = @('Entity1','Entity2','Entity3','Entity4')
    
    #Format Table will automatically output to console without the need to format anything special
    @($object1,$object2,$object3) | ft $headers
    

    这将输出:

    Entity1 Entity2 Entity3 Entity4
    ------- ------- ------- -------
    ON      ON      OFF            
    OFF     ON              ON     
            ON      OFF     ON    
    

    【讨论】:

    • 您基本上只是手动编写该表。这有什么帮助?
    • 我相信您可以根据当前情况进行调整...您已经添加了注释属性,我只是手动镜像它以提供示例。表面上你可以这样做:英尺 $myEntities
    • 是的,这行不通,因为 $myData 包含所有信息。同样,在这种情况下,$myDaya 是一个 PSObject,其成员数等于实体数,其中名称是实体名称,值是整个 JSON。您建议的输出将是两列:一列是实体名称,另一列是整个 JSON 的转储。这显然不是我需要的。
    • 我明白你在这里得到了什么。在这种情况下,如果您只需要每个子系统的执行状态,为什么还要拉整个 JSON 文件?
    • 因为用户可能需要并且将需要同时形成多个报告。单独的执行表,单独的触发器等。所以我会使用相同的 JSON 和相同的代码,只更改要汇总的参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 1970-01-01
    • 2016-06-19
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多