2010-11-10 29 views
12

Sono nuovo di potere shell.ordinamento personalizzato in powershell

Il mio problema è che che ho i nomi dei file in formato seguente:

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

Ho bisogno di ordinare in base alle seguenti regole: decrescente per parte centrale, poi per nome, in ordine naturale (cioè foobar10> foobar2) . Non conosco il valore del prefisso, ma conosco il separatore (trattino).

quindi il mio primo tentativo, naturalmente:

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

Questo ha un problema che il suffisso colpisce ordine (ignorare-aaa-1ignore-wname) è ordinata prima di ignorare-aaa-2ignore-aname), in modo da:

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

Ok, questo si ordina a metà, ma già senza mezzi termini. Se devo aggiungere un tipo naturale, sarebbe anche peggio. Qual è il modo più elegante di farlo?

risposta

11

Comprendo il compito in questo modo: l'ordinamento deve essere eseguito da 3 espressioni: 1) parte centrale, 2) nome parte senza cifre, 3) numero rappresentato da cifre finali della parte nome.

Creiamo queste espressioni con espressioni regolari. Ecco la risposta:

# 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 

Per una migliore comprensione di come funziona si può provare queste espressioni separatamente:

$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 

Di conseguenza, per esempio, questi file (estensione non è importante):

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

saranno ordinati come:

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

"$ part1, $ part2, $ part2" dovrebbe essere "$ part1, $ part2, $ part3" grazie! – DennyRolling

+0

Sì, l'ho notato anche io. Fisso. –

Problemi correlati