Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

custom sorting in powershell

Tags:

powershell

I have filenames in following format:

[ignore-prefix]-[important-middle]-[ignore-suffix]-[name-with-digits]

I need to sort according to following rules: first by middle part, then by name, in natural order (i.e. foobar10 > foobar2). I don't know prefix value, but I know the separator (dash).

so my first attempt, naturally:

 filelist | Sort-Object -property @{Expression=`
       {$_.FullName.SubString($_.FullName.IndexOf("-")+1)}}

This has a problem that the suffix affects order (ignore-aaa-1ignore-wname) is sorted before ignore-aaa-2ignore-aname), so:

 $filelist | Sort-Object -property @{Expression=`
       {$_.FullName.SubString($_.FullName.IndexOf("-")+1,`
        $_.FullName.SubString($_.FullName.IndexOf("-")+1).IndexOf("-"))}}

Ok, that sorts by the middle but already unwhieldy. If I'm to add natural sort that would be even worse. What's more elegant way of doing that?

like image 667
DennyRolling Avatar asked Nov 10 '10 16:11

DennyRolling


People also ask

How do you sort data in PowerShell?

To sort the output in the PowerShell you need to use Sort-Object Pipeline cmdlet. In the below example, we will retrieve the output from the Get-Process command and we will sort the, according to memory and CPU usage.

How do I sort in ascending PowerShell?

To sort one property in ascending order and another property in descending order, the command uses a hash table for the value of the Property parameter. The hash table uses an Expression key to specify the property name and an Ascending or Descending key to specify the sort order.

How do I sort a string in PowerShell?

Each PowerShell session has its own command history. The Get-History cmdlet gets the history objects from the current PowerShell session. The objects are sent down the pipeline to the Sort-Object cmdlet. Sort-Object uses the Property parameter to sort the objects by Id.

How do I get unique values in PowerShell?

The Get-Unique cmdlet compares each item in a sorted list to the next item, eliminates duplicates, and returns only one instance of each item. The list must be sorted for the cmdlet to work properly. Get-Unique is case-sensitive. As a result, strings that differ only in character casing are considered to be unique.


2 Answers

I understand the task in this way: sorting should be performed by 3 expressions: 1) middle part, 2) name part without digits, 3) number represented by trailing digits of the name part.

Let’s create these expressions with regular expressions. Here is the answer:

# gets the middle part
$part1 = { if ($_.Name -match '^[^-]+-([^-]+)') { $matches[1] } }

# gets the name part with no digits
$part2 = { if ($_.Name -match '^[^-]+-[^-]+-[^-]+-(\D+)') { $matches[1] } }

# gets the number represented by digits from name (cast to [int]!)
$part3 = { if ($_.Name -match '^[^-]+-[^-]+-[^-]+-\D+(\d+)') { [int]$matches[1] } }

# sort it by 3 expressions
$filelist | Sort-Object $part1, $part2, $part3

For better understanding of how it works you may test these expressions separately:

$part1 = { if ($_.Name -match '^[^-]+-([^-]+)') { $matches[1] } }
$part2 = { if ($_.Name -match '^[^-]+-[^-]+-[^-]+-(\D+)') { $matches[1] } }
$part3 = { if ($_.Name -match '^[^-]+-[^-]+-[^-]+-\D+(\d+)') { [int]$matches[1] } }

Write-Host '----- test1'
$filelist | % $part1

Write-Host '----- test2'
$filelist | % $part2

Write-Host '----- test3'
$filelist | % $part3

As a result, for example, these files (extension is not important):

aaa-zzz-1ignore-wname10.txt
aaa-zzz-1ignore-wname2.txt
ignore-aaa-1ignore-wname10.txt
ignore-aaa-1ignore-wname2.txt

will be sorted like:

ignore-aaa-1ignore-wname2.txt
ignore-aaa-1ignore-wname10.txt
aaa-zzz-1ignore-wname2.txt
aaa-zzz-1ignore-wname10.txt
like image 60
Roman Kuzmin Avatar answered Sep 18 '22 15:09

Roman Kuzmin


Does this do it?

 ls | sort { ($_ -split '-')[1] }

       Directory: C:\users\js\foo


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        7/22/2019   5:20 PM             10 pre-aaa-zuf-joe111
-a----        7/22/2019   5:20 PM             10 bre-aab-suf-joe112
-a----        7/22/2019   5:20 PM             10 pre-aac-auf-joe113
like image 26
js2010 Avatar answered Sep 20 '22 15:09

js2010