PowerShell自定义排序排序

12

我有一个简单脚本,运行第三方应用程序的 cmdlet 并输出一个包含 3 列的表格 - Name, Result, JobNameResult 只包含三个值之一: Success, Warning, 或者 Failed

输出:

Name      Result   JobName                          
----      ------   -------                          
server1   Success  servers-A            
server2   Success  servers-A            
server3   Warning  servers-A            
server4   Success  servers-A   
server5   Warning  servers-B            
server6   Success  servers-B            
server7   Failed   servers-C            
server8   Failed   servers-C   

我想要做的是按照以下自定义顺序(重要性顺序)对表格按 Result 列进行排序:Failed, Warning, 然后是Success

示例

Name    Result  JobName    
----    ------  -------                      
server7 Failed  servers-C            
server8 Failed  servers-C
server3 Warning servers-A            
server5 Warning servers-B            
server1 Success servers-A            
server2 Success servers-A            
server4 Success servers-A   
server6 Success servers-B

如何实现这个目标?


你能否发布你的代码,这样我们就可以看到它是如何实现的?你可以在 Sort-Object 命令中指定 -decending 开关,但查看你的代码将有助于确切地了解该怎么做。 - Ross Lyons
3个回答

29
您可以使用Array.IndexOf(),它可以将字符串有效地转换为数字:
$importance = "Failed", "Warning", "Success"

$result | Sort-Object { $importance.IndexOf($_.Result) }

提示:如果Result中出现了意外值,它将被排到最前面,因为IndexOf在找不到值时会返回-1。

测试:

$importance = "Failed", "Warning", "Success"

$list = @(
    @{ Result = "Warning" }
    @{ Result = "Success" }
    @{ Result = "Failed" }
)

$list | Sort-Object { $importance.IndexOf($_.Result) }

结果:

名称                           值                                                                                                                                                                 
----                           -----                                                                                                                                                                 
结果                         失败                                                                                                                                                                
结果                         警告                                                                                                                                                               
结果                         成功                                                                                                                                                               

这太妙了!当在 Sort-Object 中提供一个脚本块时,数组将根据脚本块的输出进行排序,此时输出将类似于 -1;-1;0;-1;-1;2;-1-1;1 ,当你对其进行排序时,你会得到 -1;-1;-1;-1;-1;0;1;2 。看起来脚本块就像是附加到原始数组上的临时列。 - Vasil Nikolov
@Vasil 是的,这正是它所做的 - 它可以按任何表达式进行排序。最简单的表达式可能是“原始对象的某个属性”,但“我刚刚计算出来的某个值”也可以完全相同地工作。 - Tomalak
1
@KarthickGanesan Sort-Object { ... } 会针对输入中的每个项来评估脚本块。然后使用脚本块的结果进行排序。在上述代码中,脚本块的结果是输入字符串在 $importance 数组中的数字索引。因此,该数组的顺序决定了事物排序的顺序。 - Tomalak
@Tomalak,有没有一种简单的方法来扩展这个概念以对多个属性上的对象进行排序?你只需要添加IndexOf值吗? - krick
@krick 是的。您可以计算多个属性进行排序,请参阅Sort-Object文档。在Expression中,您可以使用脚本块{ ... }而不是字符串(即属性名称),就像答案中所示。 - Tomalak
显示剩余2条评论

7

这里有一个脚本块选项:

ForEach ($Result in 'Success','Warning','Failed') {
    $Obj | Where-Object {$_.Result -eq $Result } | Sort-Object Name
}

假设您的 cmdlet 已经将原始对象输出到名为 $Obj 的变量中。

谢谢,你的建议对我很有帮助!为了让事情更加复杂,是否可以按名称排序?我想要的结果列已经排好序了,但名称对象(服务器名称)是随机的。再次感谢。 - scatterbits
是的,我们可以在 Where-Object 之后添加它。我已经编辑并包含了它。 - Mark Wragg

0

这是我如何做到的,你传递包含对象和你想要排序的属性名称,它会将一个正确排序的对象带回来,而不必尝试绕过 sort-object 命令(这很棒),而不知道其底层发生了什么。希望这可以帮助到你。

function sortObjectManually
{
    Param(
    [parameter(Mandatory=$true)]
    $unsortedObject,
    [parameter(Mandatory=$true)]
    $propertyName
    )
    
    $sortedObject = New-Object System.Collections.ArrayList;
    foreach ($object in $unsortedObject)
    {
        if ($sortedObject.Count -eq 0)
        {
            $sortedObject.Add($object) | Out-Null;
        }
        else
        {
            $inserted = $false;
            for ($i = 0; $i -lt $sortedObject.Count; $i++)
            {
                if ($object.$propertyName -lt $sortedObject[$i].$propertyName)
                {
                    $sortedObject.Insert($i, $object);
                    $inserted = $true;
                    break;
                }
            }
            
            if ($inserted -eq $false)
            {
                $sortedObject.Add($object) | Out-Null;
            }
        }
    }
    
    return $sortedObject;
}

cls;
$prop = "ServerName";
$results = sortObjectManually -unsortedObject $endInvokeArr -propertyName $prop;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接