Powershell中的自定义排序

Powershell中的自定义排序

本文介绍了Powershell中的自定义排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下格式的文件名:

I have filenames in following format:

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

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

I need to sort according to following rules: first by middle part, then by name, in natural order (i.e. foobar10 > foobar2). I don't know prefix value, but I know the separator (dash).

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

so my first attempt, naturally:

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

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

This has a problem that the suffix affects order (ignore-aaa-1ignore-wname) is sorted before ignore-aaa-2ignore-aname), so:

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

好的,按中间排序,但已经很笨拙了.如果我要添加自然排序,那就更糟了.有什么更优雅的方式来做到这一点?

Ok, that sorts by the middle but already unwhieldy. If I'm to add natural sort that would be even worse. What's more elegant way of doing that?

推荐答案

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

I understand the task in this way: sorting should be performed by 3 expressions: 1) middle part, 2) name part without digits, 3) number represented by trailing digits of the name part.

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

Let’s create these expressions with regular expressions. Here is the answer:

# 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

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

For better understanding of how it works you may test these expressions separately:

$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

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

As a result, for example, these files (extension is not important):

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

这篇关于Powershell中的自定义排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 17:57