Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort-Object not sorting correctly due to encoding issue

When I run the following code:

'Windows Embedded Standard',
'Windows 7 Enterprise',
'Windows XP Professional',
'Windows Server 2003',
'Windows 7 Entreprise',
'',
'Windows 7 Professionnel',
'Windows 7 Professional',
'Windows 10 Enterprise',
'Windows Server 2008 R2 Standard',
'Windows Server 2012 Standard',
'Windows Server 2012 R2 Standard',
'unknown',
'Windows Server 2008 R2 Enterprise' | Sort-Object

It sorts as following:

unknown
Windows 10 Enterprise
Windows 7 Enterprise
Windows 7 Professional
Windows 7 Professionnel
Windows Embedded Standard
Windows Server 2003
Windows Server 2008 R2 Enterprise
Windows Server 2008 R2 Standard
Windows Server 2012 R2 Standard
Windows Server 2012 Standard
Windows XP Professional
Windows 7 Entreprise

I can't figure out why the last entry Windows 7 Entreprise is not correctly sorted. It should come in the 4th position. What am I missing here?

UPDATE

Thanks to the comments it became clear that the source data seems to be the problem:

$Computers = Get-ADComputer -SearchBase 'OU=EU,DC=domain,DC=net' -Filter * -Properties OperatingSystem
$Computers | Group-Object OperatingSystem | Sort-Object Name | Select-Object Count, Name | Format-Table -AutoSize

ANSI Values:

$Computers | Group-Object OperatingSystem | ForEach-Object{$_.Name;[int[]][char[]]$_.Name -join "|"}
Windows Server 2008 R2 Standard
87|105|110|100|111|119|115|32|83|101|114|118|101|114|32|50|48|48|56|32|82|50|32|83|116|97|110|100|97|114|100
Windows Server 2003
87|105|110|100|111|119|115|32|83|101|114|118|101|114|32|50|48|48|51
Windows Server 2012 Standard
87|105|110|100|111|119|115|32|83|101|114|118|101|114|32|50|48|49|50|32|83|116|97|110|100|97|114|100


Windows Server 2012 R2 Standard
87|105|110|100|111|119|115|32|83|101|114|118|101|114|32|50|48|49|50|32|82|50|32|83|116|97|110|100|97|114|100
unknown
117|110|107|110|111|119|110
Windows Server 2008 R2 Enterprise
87|105|110|100|111|119|115|32|83|101|114|118|101|114|32|50|48|48|56|32|82|50|32|69|110|116|101|114|112|114|105|115|101
Windows 7 Enterprise
87|105|110|100|111|119|115|32|55|32|69|110|116|101|114|112|114|105|115|101
Windows 7 Entreprise
87|105|110|100|111|119|115|160|55|32|69|110|116|114|101|112|114|105|115|101
Windows 7 Professionnel
87|105|110|100|111|119|115|32|55|32|80|114|111|102|101|115|115|105|111|110|110|101|108
Windows XP Professional
87|105|110|100|111|119|115|32|88|80|32|80|114|111|102|101|115|115|105|111|110|97|108
Windows 7 Professional
87|105|110|100|111|119|115|32|55|32|80|114|111|102|101|115|115|105|111|110|97|108
Windows 10 Enterprise
87|105|110|100|111|119|115|32|49|48|32|69|110|116|101|114|112|114|105|115|101
Windows Embedded Standard
87|105|110|100|111|119|115|32|69|109|98|101|100|100|101|100|32|83|116|97|110|100|97|114|100

Is there a way to encode it differently so PowerShell can sort this correctly?

like image 377
DarkLite1 Avatar asked Sep 23 '26 01:09

DarkLite1


1 Answers

Use the String.Normalize() function with Normalization Form KC or KD (documented here):

$Computers = Get-ADComputer -SearchBase 'OU=EU,DC=domain,DC=net' -Filter * -Properties OperatingSystem
$OSList = $Computers | Select-Object -ExpandProperty OperatingSystem | ForEach-Object {
    $_.ToString().Normalize([Text.NormalizationForm]::FormKC)
}

Note that the Normalize function will remote diacritics such as accents and graves. For example, á will beome a. In order to convert character 160 to character 32, I had to use one of the normalization forms that used "full compatibility decomposition," which is either the KC or KD form.

like image 103
JamesQMurphy Avatar answered Sep 25 '26 00:09

JamesQMurphy