使用Powershell对CSV文件进行排序

使用Powershell对CSV文件进行排序,powershell,csv,Powershell,Csv,我正在尝试对一个大的CSV文件进行排序。问题在于在名为Combined的冒号上使用sort对象。它不像我期望的那样!为了进行测试,我删除了所有未排序的数据,并减少了行数 原始CSV: Combined 1A THE BIG 7 3A SPRING 19 LUZREN 21 23 25 29 1 HONEY 5 3 THE GOOD 11 ARVALA BRASAID 13 MEADOWCLAW Powershell: Import-Csv orginal.csv -delimiter ','

我正在尝试对一个大的CSV文件进行排序。问题在于在名为Combined的冒号上使用sort对象。它不像我期望的那样!为了进行测试,我删除了所有未排序的数据,并减少了行数

原始CSV:

Combined
1A THE BIG
7
3A SPRING
19
LUZREN
21
23
25
29
1 HONEY
5
3 THE GOOD
11
ARVALA
BRASAID
13
MEADOWCLAW
Powershell:

Import-Csv orginal.csv -delimiter ',' | Sort-Object -Unique Combined 

Combined
--------
1 HONEY
11
13
19
1A THE BIG
21
23
25
29
3 THE GOOD
3A SPRING
5
7
ARVALA
BRASAID
LUZREN
MEADOWCLAW
我所期望的是:

Combined
1A THE BIG
5
7
11
13
19
21
23
25
29
1 HONEY
3 THE GOOD
3A SPRING
ARVALA
BRASAID
LUZREN
MEADOWCLAW
在一个完美的世界里,我希望:

Combined
1A THE BIG
1 HONEY
3 THE GOOD
3A SPRING
5
7
11
13
19
21
23
25
29
ARVALA
BRASAID
LUZREN
MEADOWCLAW
有人能给我解释一下为什么会发生这种事吗?一个星期以来我一直在用头撞显示器。还有,我怎样才能得到我想要的输出


谢谢你

导入CSV
默认情况下将所有值作为
字符串导入。这就是为什么你会得到你所看到的结果。它是按字母顺序排列的。字母数字中的“优先级”是:空格、数字、字母

我认为如果没有一些严肃的代码,你就无法得到你想要的输出。我唯一的建议是将纯数字解析为int,例如,数字30将出现在5之后。这可以通过以下方式完成:

$intvalue = 10000
import-csv .\test.csv | % {
    if ([int]::TryParse($_.Combined, [ref]$intvalue)) {
        $_.Combined = $intvalue
    }
    $_
} | Sort-Object -Unique Combined

Combined
--------
1 HONEY
5
7
11
13
19
1A THE BIG
21
23
25
29
3 THE GOOD
3A SPRING
ARVALA
BRASAID
LUZREN 
MEADOWCLAW 
试试这个:(不是在完美的世界里)

按照@Aryadev的正确答案,此代码排序值也以多个数字开头:

$allToNumbers = { [int]([regex]::Replace( $_.combined , "\D" , "" )) }
$StartsWithNumber = { if ($_.Combined -match '^\d+\D') { $_.Combined } }
$IsNumber = { if ($_.Combined -match '^\d*$') { [int]$_.Combined } }
$OnlyLetters = { if ($_.Combined -imatch '^[a-z ]*$') { $_.Combined } }

Import-Csv original.csv | 
Sort-Object  $OnlyLetters, $allnumbers, $IsNumber,  $StartsWithNumber -Unique

我不确定是否理解排序逻辑,但请尝试以下方法:

$StartsWithNumber = { if ($_.Combined -match '^\d*\D' ) { $_.Combined } }
$IsNumber = { if ($_.Combined -match '^\d*$') { [int]$_.Combined } }
$OnlyLetters = { if ($_.Combined -imatch '^[a-z ]*$') { $_.Combined } }

Import-Csv original.csv | 
Sort-Object $OnlyLetters, $IsNumber, $StartsWithNumber -Unique

Combined
--------
1 HONEY
1A THE BIG
3 THE GOOD
3A SPRING
5
7
11
13
19
21
23
25
29
ARVALA
BRASAID
LUZREN
MEADOWCLAW

默认排序是逐符号排序。为什么“1A大”应该排在“1亲爱的”之前?它像字符串一样对它们进行排序,这就是它应该如何工作的。如果将每个数字视为a前面的字母,则将其视为字母排序非常有意义。+1我认为$startsWithNumer中的正则表达式最好是这样“^\d*\d”,以防某些值以一个以上的单个数字开头。对吧?太好了!我的完美世界输出是错误的(我的坏)。你的解决方案输出了我所需要的。谢谢
$StartsWithNumber = { if ($_.Combined -match '^\d*\D' ) { $_.Combined } }
$IsNumber = { if ($_.Combined -match '^\d*$') { [int]$_.Combined } }
$OnlyLetters = { if ($_.Combined -imatch '^[a-z ]*$') { $_.Combined } }

Import-Csv original.csv | 
Sort-Object $OnlyLetters, $IsNumber, $StartsWithNumber -Unique

Combined
--------
1 HONEY
1A THE BIG
3 THE GOOD
3A SPRING
5
7
11
13
19
21
23
25
29
ARVALA
BRASAID
LUZREN
MEADOWCLAW