пользовательская сортировка в powershell - PullRequest
13 голосов
/ 10 ноября 2010

Я новичок в Power Shell.

Моя проблема в том, что у меня есть имена файлов в следующем формате:

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

Мне нужно отсортировать по следующим правилам: сначала по серединечасть, затем по имени, в естественном порядке (т.е. foobar10> foobar2).Я не знаю значения префикса, но я знаю разделитель (тире).

, поэтому моя первая попытка, естественно:

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

Проблема в том, что суффикс влияет на порядок (игнорировать-aaa-1ignore-wname) сортируется перед ignore-aaa-2ignore-aname), поэтому:

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

Хорошо, сортировка по середине, но уже громоздкая.Если бы я добавил натуральную сортировку, это было бы еще хуже.Какой более элегантный способ сделать это?

1 Ответ

14 голосов
/ 10 ноября 2010

Я понимаю задачу следующим образом: сортировка должна выполняться по 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...