Search code examples
regexpowershellsortingmatchsort-object

PowerShell Sort by 2nd Index


I'm trying to sort servers by the 2nd index of the name. The server names are taken from file paths where they are the BaseName of the file. I know that Select-Object has the parameter -Index, but I don't think that will work. I am assuming that the best approach is with a PowerShell RegEx like "(?:^a-z))". This returns an unsorted list and I'm still googling around for a pattern that will sort by the 2nd Index.

Example of the Intended Output

  • Group the servers by name CC or DD
Server        
------        
ABCCWS01
CDCCWS01
ABDDWS01
CDDDWS01

Current Output

  • Sorts alphabetically by -Property name
$servers = Get-Item -Path
C:\ABDDWS01.ServerData, 
C:\ABCCWS01.ServerData, 
C:\CDCCWS01.ServerData, 
C:\CDDDWS01.ServerData | Group BaseName -AsHashtable

foreach($computer in $servers.GetEnumerator() | Sort-Object -Property name)
{ ...DoSomething... }

Server        
------        
ABCCWS01
ABDDWS01
CDCCWS01
CDDDWS01

Then I tried to implement a PowerShell RegEx. But I'm stuck on how to properly use this to sort by the 2nd index. This example has no affect and returns the list unsorted. I've tried subbing in different patterns at the end "(?:^a-z))". So far my attempts either return the list unsorted or just a segment of the list. I've googled around and tried many different things. If someone else wants to help puzzle this out, it is much appreciated.

Sort-Object -Property @{Expression={[RegEx]::Match($_.basename, "(?:^a-z))")}}

Solution

  • Sort-Object works by "ranking" each input according to the resulting value of calculating one or more property expressions against each input item - in your existing example, based on the the value of the name property.

    As you've already found, property expressions doesn't have to be the value of any existing property though - they can be made up of anything - just pass a script block in place of the property name:

    ... |Sort-Object -Property {$_.name[1]}
    

    The reason it doesn't work in your example is that the expression [RegEx]::Match($_.basename, "(?:^a-z))") returns a [System.Text.RegularExpressions.Match] object - and those can't be meaningfully compared to one another.

    If you change the expression to resolve to a string instead (the matched value for example), it'll work:

    ... |Sort-Object -Property @{Expression={[RegEx]::Match($_.basename, "(?:^a-z))").Value}}
    # or
    ... |Sort-Object -Property {[RegEx]::Match($_.basename, "(?:^a-z))").Value}