2010-11-10 78 views
12

我是电源外壳的新手。在PowerShell中自定义排序

我的问题是,我在下面的格式文件名:

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

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

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

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

这有后缀影响顺序(忽略-AAA-1ignore-wname)忽略-AAA-2ignore-aname),所以之前排序的问题:

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

好吧,那种在中间,但已经不笨。如果我要添加更糟糕的自然排序。什么更优雅的方式来做到这一点?

回答

11

我以这种方式理解任务:排序应该由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 

为了更好地理解它是如何运作的,你可以分别测试这些表达式:

$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 

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

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

进行排序,如:

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

“$ part1,$ part2,$ part2”应该是“$ part1,$ part2,$ part3” 谢谢! – DennyRolling 2010-11-10 17:27:51

+0

是的,我也注意到了。固定。 – 2010-11-10 17:30:37