【问题标题】:Group and select objects from CSV in PowerShell在 PowerShell 中从 CSV 分组和选择对象
【发布时间】:2020-07-03 18:38:17
【问题描述】:

我有一个用户列表,其中包含他们的设备和他们的管理员。 manager 和 user 可以重复,但 deviceID 是唯一的。我如何获得一份清单,以便我可以向每位经理发送一封电子邮件,让他们知道他们的员工正在使用多少个单位和哪个单位?我只对拥有 2 台或更多设备的人感兴趣。

想要的输出是这样的(如果有人想给我一个更好的输出建议,我会全力以赴)。

Manager  deviceID
M1        U1=D1 D2, U3=D4 D5

我的代码现在的样子:

$csv = @"
manager,user,deviceID
M1,U1,D1
M1,U1,D2
M2,U2,D3
M1,U3,D4
M1,U3,D5
"@ -split "`r`n" | ConvertFrom-Csv

$csv | Group-Object -Property Manager |
     Select-Object @{N='Manager';E={($_.Group[0]).Manager}}, 
@{N="User";E={($_.group).user}}, 
@{N="deviceID";E={ foreach($row in $_.Group){ $row.user + ' = ' + $row.deviceID}}} 

【问题讨论】:

    标签: powershell select-object


    【解决方案1】:

    既然您说您只对列出使用多台设备的用户感兴趣,也许这可以帮助您:

    $csv = @"
    manager,user,deviceID
    M1,U1,D1
    M1,U1,D2
    M2,U2,D3
    M1,U3,D4
    M1,U3,D5
    "@ -split "`r`n" | ConvertFrom-Csv
    
    # first group on Manager
    $result = $csv | Group-Object -Property Manager | ForEach-Object {
        $manager = $_.Name
        # next, group the groups on User and select only where a user is mentioned twice or more times
        $_.Group | Group-Object User | Where-Object { $_.Count -gt 1 } | ForEach-Object {
            [PsCustomObject]@{
                Manager = $manager
                User = $_.Name
                Devices = $_.Group.DeviceID -join ' '
            }
        }
    }
    
    # output on screen
    $result
    
    # output to CSV
    $result | Export-Csv -Path 'managerReport.csv' -NoTypeInformation
    

    输出:

    Manager User Devices
    ------- ---- -------
    M1      U1   D1 D2  
    M1      U3   D4 D5
    
    # to separate the results so each manager gets his/her personal report:
    $result | Group-Object Manager | ForEach-Object {
        # send an email to the manager. For demo just output to console
        Write-Host "Send mail to manager $($_.Name):" -ForegroundColor Yellow
        $_.Group | Format-Table -AutoSize | Out-String
    }
    

    【讨论】:

      【解决方案2】:

      这是一个 HashTable 方法:

      $managerGroups = $csv | Group-Object -Property manager -AsHashTable
      
      foreach ($item in $managerGroups.GetEnumerator()) {
          $userGroups = $item.Value | Group-Object -Property user -AsHashTable
      
          & {
              [PSCustomObject]@{
                  Manager = $item.Key
                  DeviceId = & {
                      foreach ($user in $userGroups.GetEnumerator()) {
                          [PSCustomObject]@{
                              User = $user.Key
                              Devices = & {
                                  foreach ($device in $user.Value) {
                                      $device.deviceID
                                  }
                              }
                          }
                      }
                  }
              }
          } | Select-Object -Property Manager, @{
              Name='DeviceId';
              Expression={
                  & {
                      foreach ($deviceId in $_.DeviceId) {
                          "$($deviceId.User) = $($deviceId.Devices -join " ")"
                      }
                  } | Join-String -Separator ", "
              }
          }
      }
      

      输出:

      Manager DeviceId
      ------- --------
      M1      U1 = D1 D2, U3 = D4 D5
      M2      U2 = D3
      

      说明:

      您也可以使用完整的管道方法:

      $managerGroups = $csv | Group-Object -Property manager -AsHashTable
      
      $managerGroups.GetEnumerator() | Foreach-Object {
          $manager = $_.Key
      
          $userGroups = $_.Value | Group-Object -Property user -AsHashTable
      
          [PSCustomObject]@{
              Manager = $manager
              DeviceId = $userGroups.GetEnumerator() | ForEach-Object {
                  [PSCustomObject]@{
                      User = $_.Key
                      Devices = $_.Value | ForEach-Object {$_.deviceId}
                  }
              }
          } | Select-Object -Property Manager, @{
              Name='DeviceId';
              Expression={
                  $_.DeviceId | ForEach-Object { 
                      "$($_.User) = $($_.Devices -join " ")"
                  } | Join-String -Separator ', '
              }
          }
      }
      

      这可能会更慢,因为在使用 .NET 类型或 [PSCustomObject] 时,foreach 成员枚举比 Foreach-Object 管道快得多。您可以查看answer 了解更多信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-01-10
        • 1970-01-01
        • 2022-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多