PowerShell中的自定义排序

Den*_*ing 13 powershell

我是动力贝壳的新手.

我的问题是我有以下格式的文件名:

[ignore-prefix]-[important-middle]-[ignore-suffix]-[name-with-digits]
Run Code Online (Sandbox Code Playgroud)

我需要按照以下规则排序:首先按中间部分,然后按名称按自然顺序排序(即foobar10> foobar2).我不知道前缀值,但我知道分隔符(破折号).

所以我的第一次尝试,自然:

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

这有一个问题,后缀影响顺序(ignore-aaa-1ignore-wname)在ignore-aaa-2ignore-aname之前排序,所以:

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

好吧,那个在中间排序,但已经不合时宜了.如果我要添加更糟糕的自然类型.这样做更优雅的方式是什么?

Rom*_*min 14

我以这种方式理解任务:排序应该由3个表达式执行:1)中间部分,2)没有数字的名称部分,3)名称部分的尾随数字表示的数字.

让我们用正则表达式创建这些表达式.这是答案:

# 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
Run Code Online (Sandbox Code Playgroud)

为了更好地理解它的工作原理,您可以单独测试这些表达式:

$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
Run Code Online (Sandbox Code Playgroud)

因此,例如,这些文件(扩展名并不重要):

aaa-zzz-1ignore-wname10.txt
aaa-zzz-1ignore-wname2.txt
ignore-aaa-1ignore-wname10.txt
ignore-aaa-1ignore-wname2.txt
Run Code Online (Sandbox Code Playgroud)

将按如下排序:

ignore-aaa-1ignore-wname2.txt
ignore-aaa-1ignore-wname10.txt
aaa-zzz-1ignore-wname2.txt
aaa-zzz-1ignore-wname10.txt
Run Code Online (Sandbox Code Playgroud)