开发者

custom sorting in 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 -pro开发者_如何学Cperty @{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?


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


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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜