在PowerShell中将非唯一值与唯一字段并置

时间:2019-11-06 17:46:59

标签: powershell

我有以下查询集合,它们检索一组数据,将其合并下来,这样我就可以获得唯一的值,并向每个值添加一个数字(以便以后可以选择该特定项)。

$allMoveRequests = Get-MoveRequest -DomainController server | 
    select Alias,Status,TargetDatabase,BatchName 

$optNum=1
$AllMoveBatches = @($allMoveRequests | Sort-Object -Property BatchName | 
    Select-Object BatchName,TargetDatabase -Unique) |
    Select @{Name="Option";Expression={$optNum;$optNum++}},BatchName,TargetDatabase

$AllMoveBatches | Format-Table -AutoSize | Out-String|% {Write-Host $_}

这将返回:

Option BatchName TargetDatabase
------ --------- --------------
1      Batch1    Database1
2      Batch2    Database2

等那样就可以了,但是我要添加的是这些批处理中的“状态”值,这些值在不止一个的情况下合并在一起,而不是创建重复的条目。例如,如果我只是将Status添加到第二行代码中,则最终得到:

Option BatchName TargetDatabase Status
------ --------- -------------- ------
1      Batch1    Database1      Completed
2      Batch1    Database1      In Progress
3      Batch2    Database2      Completed

而我理想的情况是:

Option BatchName TargetDatabase Status
------ --------- -------------- ------
1      Batch1    Database1      Completed,InProgress
2      Batch2    Database2      Completed

我尝试在select语句中使用表达式查询所有相关的Status条目并将-Unique应用于它们,但这只会返回所有批次中的所有Status条目,而不仅仅是返回与当前Batch行相关的状态。 / p>

有没有办法做到这一点?

2 个答案:

答案 0 :(得分:2)

这不是很漂亮,而且在处理大量数据时可能表现不佳,但这是一种实现方法...

首先,让我们创建一些示例数据:

$data = @(
    (new-object PSObject -Property ([ordered] @{
        "BatchName"      = "Batch1"
        "TargetDatabase" = "Database1"
        "Status"         = "Completed"
    })),
    (new-object PSObject -Property ([ordered] @{
        "BatchName"      = "Batch1"
        "TargetDatabase" = "Database1"
        "Status"         = "In Progress"
    })),
    (new-object PSObject  -Property ([ordered] @{
        "BatchName"      = "Batch2"
        "TargetDatabase" = "Database2"
        "Status"         = "Completed"
    }))
)

现在,对其进行处理:

Set-Variable -Name "optNum" -Option AllScope -Value 1
$results = @( $data | group-object BatchName, TargetDatabase ) `
    | select-object @{Name="Option";Expression={$optNum; $optNum++}},
                    @{Name="BatchName";Expression={$_.Group[0].BatchName}},
                    @{Name="TargetDatabase";Expression={$_.Group[0].TargetDatabase}},
                    @{Name="Status";Expression={$_.Group.Status -join ", "}} `
    | sort-object -Property BatchName

并显示结果:

PS> $results

Option BatchName TargetDatabase Status
------ --------- -------------- ------
     1 Batch1    Database1      Completed, In Progress
     2 Batch2    Database2      Completed

它的作用是分组,以选择BatchName和DatabaseName的唯一组合,然后生成结果,即从每个组的第一项中选择BatchName和DatabaseName,并串联所有状态。该组中项目的属性(如果要在每个组中对它们进行排序,过滤或重复数据删除,也可以在状态表达式中处理状态)。

请注意,我已经将您原来的sort-object BatchName移到了管道的末尾。毫无意义的排序,比如说1000个对象只能扔掉一半-您最好在最后进行排序。

而且我只能通过使用Set-Variable将其设置为AllScope来使您的“ Option”计数器起作用,因为当我使用$optNum++$optNum = 1没有正确地增加变量进行初始化。

答案 1 :(得分:1)

mclayton的答案应该是被接受的答案,但这是一个更简洁的版本,它使用了我最喜欢的Powershell惯用法之一:Foreach-Begin脚本块{$i=1},该脚本只能执行一次。

[pscustomobject]@{BatchName = 'Batch1';TargetDatabase='Database1';Status='Completed'},
[pscustomobject]@{BatchName = 'Batch1';TargetDatabase='Database1';Status='In Progress'},
[pscustomobject]@{BatchName = 'Batch2';TargetDatabase='Database2';Status='Completed'} |
    Group BatchName, TargetDatabase | 
    %{$i=1}{ [pscustomobject]@{Option = $i++ 
            BatchName = $_.Group[0].BatchName
            TargetDatabase = $_.Group[0].TargetDatabase
            Status = $_.Group.Status -join ','}
    } 
相关问题