2010-11-10 56 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