Home > Windows にまつわる e.t.c.

PowerShell の Sort-Object Tips


データーを sort すると言えば、その昔は sort.exe、最近ならば Excel って方が多いのではないでしょうか?

実は PowerShell の Sort-Object コマンドレットって意外と優秀だったりします。

PowerShell のコマンドレットなので、オブジェクトを sort するのが仕事なのですが、Import-Csv で CSV ファイルを読んだり、Get-xxx コマンドレットで取得したデータも sort 出来ますね。

Sort-Object ではこんな事が出来ます。

■ 1プロパティを指定した sort
■ 複数プロパティを指定した 昇順 sort
■ 複数プロパティを指定した 降順 sort
■ プロパティ別に照準/降順を指定した sort
■ 重複排除
■ IPv4 アドレス sort
■ 数字 sort

 

1プロパティを指定した 昇順 sort

まずは sort 対象の CSV ファイル(HostRole.csv)を読み込みこんで表示します。

# CSV データーの読み込み
$CSVData = Import-Csv .\HostRole.csv

# CSV データーの表示
$CSVData | ft * -AutoSize

 

PS C:\Temp> # CSV データーの読み込み
PS C:\Temp> $CSVData = Import-Csv .\HostRole.csv
PS C:\Temp>
PS C:\Temp> # CSV データーの表示
PS C:\Temp> $CSVData | ft * -AutoSize

HostName  IPAddress    CNAME                Role
--------  ---------    -----                ----
a04813-ap 10.20.42.101 Project001-ap001     AP-A
a04812-ap 10.20.42.102 Project001-ap002     AP-A
a05029-ap 10.20.42.103 Project001-ap003     AP-A
a05028-ap 10.20.42.104 Project001-ap004     AP-A
a04811-ap 10.20.42.121 Project001-ap021     AP-B
a04810-ap 10.20.42.122 Project001-ap022     AP-B
a04927-ap 10.20.42.124 Project001-ap024     AP-B
a05023-ap 10.20.42.125 Project001-ap025     AP-B
a05022-ap 10.20.42.126 Project001-ap026     AP-B
a05021-ap 10.20.42.127 Project001-ap027     AP-B
a05020-ap 10.20.42.128 Project001-ap028     AP-B
a05019-ap 10.20.42.129 Project001-ap029     AP-B
a05018-ap 10.20.42.130 Project001-ap030     AP-B
a05017-ap 10.20.42.131 Project001-ap031     AP-B
a05125-ap 10.20.42.133 Project001-ap033     AP-B
a06512-ap 172.18.42.53 Project001-domain003 ADDS
a06627-ap 172.18.42.54 Project001-domain004 ADDS
a06514-ap 10.20.42.193 Project001-admin003  ADMIN
a06629-ap 10.20.42.194 Project001-admin004  ADMIN
a04804-db 10.20.42.201 Project001-db001     DB
a04802-db 10.20.42.202 Project001-db002     DB
a04904-db 10.20.42.211 Project001-db011     DB
a04902-db 10.20.42.212 Project001-db012     DB
a03429-ap 10.20.2.116  Project001-deploy002 DPL
a06513-ap 10.20.42.93  Project001-bt003     BT
a06628-ap 10.20.42.94  Project001-bt004     BT

 

これを Role で sort してみます。

# Role で sort
Sort-Object -Property Role

 

PS C:\Temp> $CSVData | Sort-Object -Property Role | ft * -AutoSize

HostName  IPAddress    CNAME                Role
--------  ---------    -----                ----
a06512-ap 172.18.42.53 Project001-domain003 ADDS
a06627-ap 172.18.42.54 Project001-domain004 ADDS
a06629-ap 10.20.42.194 Project001-admin004  ADMIN
a06514-ap 10.20.42.193 Project001-admin003  ADMIN
a04813-ap 10.20.42.101 Project001-ap001     AP-A
a04812-ap 10.20.42.102 Project001-ap002     AP-A
a05029-ap 10.20.42.103 Project001-ap003     AP-A
a05028-ap 10.20.42.104 Project001-ap004     AP-A
a05018-ap 10.20.42.130 Project001-ap030     AP-B
a05017-ap 10.20.42.131 Project001-ap031     AP-B
a05125-ap 10.20.42.133 Project001-ap033     AP-B
a05019-ap 10.20.42.129 Project001-ap029     AP-B
a04927-ap 10.20.42.124 Project001-ap024     AP-B
a04810-ap 10.20.42.122 Project001-ap022     AP-B
a04811-ap 10.20.42.121 Project001-ap021     AP-B
a05023-ap 10.20.42.125 Project001-ap025     AP-B
a05020-ap 10.20.42.128 Project001-ap028     AP-B
a05021-ap 10.20.42.127 Project001-ap027     AP-B
a05022-ap 10.20.42.126 Project001-ap026     AP-B
a06513-ap 10.20.42.93  Project001-bt003     BT
a06628-ap 10.20.42.94  Project001-bt004     BT
a04802-db 10.20.42.202 Project001-db002     DB
a04804-db 10.20.42.201 Project001-db001     DB
a04904-db 10.20.42.211 Project001-db011     DB
a04902-db 10.20.42.212 Project001-db012     DB
a03429-ap 10.20.2.116  Project001-deploy002 DPL

 

複数プロパティを指定した 昇順 sort

複数プロパティを sort key に指定する場合は、-Property にプロパティをカンマ区切りで複数書きます。

# Role + CNAME で 昇順 sort
Sort-Object -Property Role, CNAME

 

Sort-Object は sort に、-Property は省略可能なので、このように省略できます

# 省略形
sort Role, CNAME

 

PS C:\Temp> $CSVData | sort Role, CNAME | ft * -AutoSize

HostName  IPAddress    CNAME                Role
--------  ---------    -----                ----
a06512-ap 172.18.42.53 Project001-domain003 ADDS
a06627-ap 172.18.42.54 Project001-domain004 ADDS
a06514-ap 10.20.42.193 Project001-admin003  ADMIN
a06629-ap 10.20.42.194 Project001-admin004  ADMIN
a04813-ap 10.20.42.101 Project001-ap001     AP-A
a04812-ap 10.20.42.102 Project001-ap002     AP-A
a05029-ap 10.20.42.103 Project001-ap003     AP-A
a05028-ap 10.20.42.104 Project001-ap004     AP-A
a04811-ap 10.20.42.121 Project001-ap021     AP-B
a04810-ap 10.20.42.122 Project001-ap022     AP-B
a04927-ap 10.20.42.124 Project001-ap024     AP-B
a05023-ap 10.20.42.125 Project001-ap025     AP-B
a05022-ap 10.20.42.126 Project001-ap026     AP-B
a05021-ap 10.20.42.127 Project001-ap027     AP-B
a05020-ap 10.20.42.128 Project001-ap028     AP-B
a05019-ap 10.20.42.129 Project001-ap029     AP-B
a05018-ap 10.20.42.130 Project001-ap030     AP-B
a05017-ap 10.20.42.131 Project001-ap031     AP-B
a05125-ap 10.20.42.133 Project001-ap033     AP-B
a06513-ap 10.20.42.93  Project001-bt003     BT
a06628-ap 10.20.42.94  Project001-bt004     BT
a04804-db 10.20.42.201 Project001-db001     DB
a04802-db 10.20.42.202 Project001-db002     DB
a04904-db 10.20.42.211 Project001-db011     DB
a04902-db 10.20.42.212 Project001-db012     DB
a03429-ap 10.20.2.116  Project001-deploy002 DPL

 

複数プロパティを指定した 降順 sort

Sort-Object は昇順が default なので、降順 sort する場合は -Descending を指定します。

# 降順 sort
sort Role, CNAME -Descending

 

PS C:\Temp> $CSVData | sort Role, CNAME -Descending | ft * -AutoSize

HostName  IPAddress    CNAME                Role
--------  ---------    -----                ----
a03429-ap 10.20.2.116  Project001-deploy002 DPL
a04902-db 10.20.42.212 Project001-db012     DB
a04904-db 10.20.42.211 Project001-db011     DB
a04802-db 10.20.42.202 Project001-db002     DB
a04804-db 10.20.42.201 Project001-db001     DB
a06628-ap 10.20.42.94  Project001-bt004     BT
a06513-ap 10.20.42.93  Project001-bt003     BT
a05125-ap 10.20.42.133 Project001-ap033     AP-B
a05017-ap 10.20.42.131 Project001-ap031     AP-B
a05018-ap 10.20.42.130 Project001-ap030     AP-B
a05019-ap 10.20.42.129 Project001-ap029     AP-B
a05020-ap 10.20.42.128 Project001-ap028     AP-B
a05021-ap 10.20.42.127 Project001-ap027     AP-B
a05022-ap 10.20.42.126 Project001-ap026     AP-B
a05023-ap 10.20.42.125 Project001-ap025     AP-B
a04927-ap 10.20.42.124 Project001-ap024     AP-B
a04810-ap 10.20.42.122 Project001-ap022     AP-B
a04811-ap 10.20.42.121 Project001-ap021     AP-B
a05028-ap 10.20.42.104 Project001-ap004     AP-A
a05029-ap 10.20.42.103 Project001-ap003     AP-A
a04812-ap 10.20.42.102 Project001-ap002     AP-A
a04813-ap 10.20.42.101 Project001-ap001     AP-A
a06629-ap 10.20.42.194 Project001-admin004  ADMIN
a06514-ap 10.20.42.193 Project001-admin003  ADMIN
a06627-ap 172.18.42.54 Project001-domain004 ADDS
a06512-ap 172.18.42.53 Project001-domain003 ADDS

 

プロパティ別に照準/降順を指定した sort

-Descending は全ての -Property に対して影響するので、プロパティ別の昇順降順指定は出来ません。

プロパティ別に降順照準を指定する場合は、ソート条件をハッシュ テーブルにして -Property に渡します。
プロパティは Expression キーで指定し、昇順降順は Ascending キーまたは Descending キーを $true/$false 指定します。

# Role(降順) + CNAME(昇順) sort
sort @{Expression="Role";Descending=$true}, @{Expression="CNAME";Descending=$false}

 

PS C:\Temp> $CSVData | sort @{Expression="Role";Descending=$true}, @{Expression="CNAME";Descending=$false} | ft * -AutoSize

HostName  IPAddress    CNAME                Role
--------  ---------    -----                ----
a03429-ap 10.20.2.116  Project001-deploy002 DPL
a04804-db 10.20.42.201 Project001-db001     DB
a04802-db 10.20.42.202 Project001-db002     DB
a04904-db 10.20.42.211 Project001-db011     DB
a04902-db 10.20.42.212 Project001-db012     DB
a06513-ap 10.20.42.93  Project001-bt003     BT
a06628-ap 10.20.42.94  Project001-bt004     BT
a04811-ap 10.20.42.121 Project001-ap021     AP-B
a04810-ap 10.20.42.122 Project001-ap022     AP-B
a04927-ap 10.20.42.124 Project001-ap024     AP-B
a05023-ap 10.20.42.125 Project001-ap025     AP-B
a05022-ap 10.20.42.126 Project001-ap026     AP-B
a05021-ap 10.20.42.127 Project001-ap027     AP-B
a05020-ap 10.20.42.128 Project001-ap028     AP-B
a05019-ap 10.20.42.129 Project001-ap029     AP-B
a05018-ap 10.20.42.130 Project001-ap030     AP-B
a05017-ap 10.20.42.131 Project001-ap031     AP-B
a05125-ap 10.20.42.133 Project001-ap033     AP-B
a04813-ap 10.20.42.101 Project001-ap001     AP-A
a04812-ap 10.20.42.102 Project001-ap002     AP-A
a05029-ap 10.20.42.103 Project001-ap003     AP-A
a05028-ap 10.20.42.104 Project001-ap004     AP-A
a06514-ap 10.20.42.193 Project001-admin003  ADMIN
a06629-ap 10.20.42.194 Project001-admin004  ADMIN
a06512-ap 172.18.42.53 Project001-domain003 ADDS
a06627-ap 172.18.42.54 Project001-domain004 ADDS

 

重複排除

重複排除は、-Unique を指定します。

# Role で重複排除
sort Role -Unique

 

PS C:\Temp> $CSVData | sort Role -Unique | ft * -AutoSize

HostName  IPAddress    CNAME                Role
--------  ---------    -----                ----
a06512-ap 172.18.42.53 Project001-domain003 ADDS
a06629-ap 10.20.42.194 Project001-admin004  ADMIN
a04813-ap 10.20.42.101 Project001-ap001     AP-A
a05018-ap 10.20.42.130 Project001-ap030     AP-B
a06513-ap 10.20.42.93  Project001-bt003     BT
a04802-db 10.20.42.202 Project001-db002     DB
a03429-ap 10.20.2.116  Project001-deploy002 DPL

 

IPv4 アドレス sort

IPv4 アドレスは、文字列として扱われるので、そのまま sort 残念な結果になってしまいます。

# IP アドレスで単純 sort
sort IPAddress

 

PS C:\Temp> $CSVData | sort IPAddress | ft * -AutoSize

HostName  IPAddress    CNAME                Role
--------  ---------    -----                ----
a03429-ap 10.20.2.116  Project001-deploy002 DPL
a04813-ap 10.20.42.101 Project001-ap001     AP-A
a04812-ap 10.20.42.102 Project001-ap002     AP-A
a05029-ap 10.20.42.103 Project001-ap003     AP-A
a05028-ap 10.20.42.104 Project001-ap004     AP-A
a04811-ap 10.20.42.121 Project001-ap021     AP-B
a04810-ap 10.20.42.122 Project001-ap022     AP-B
a04927-ap 10.20.42.124 Project001-ap024     AP-B
a05023-ap 10.20.42.125 Project001-ap025     AP-B
a05022-ap 10.20.42.126 Project001-ap026     AP-B
a05021-ap 10.20.42.127 Project001-ap027     AP-B
a05020-ap 10.20.42.128 Project001-ap028     AP-B
a05019-ap 10.20.42.129 Project001-ap029     AP-B
a05018-ap 10.20.42.130 Project001-ap030     AP-B
a05017-ap 10.20.42.131 Project001-ap031     AP-B
a05125-ap 10.20.42.133 Project001-ap033     AP-B
a06514-ap 10.20.42.193 Project001-admin003  ADMIN
a06629-ap 10.20.42.194 Project001-admin004  ADMIN
a04804-db 10.20.42.201 Project001-db001     DB
a04802-db 10.20.42.202 Project001-db002     DB
a04904-db 10.20.42.211 Project001-db011     DB
a04902-db 10.20.42.212 Project001-db012     DB
a06513-ap 10.20.42.93  Project001-bt003     BT
a06628-ap 10.20.42.94  Project001-bt004     BT
a06512-ap 172.18.42.53 Project001-domain003 ADDS
a06627-ap 172.18.42.54 Project001-domain004 ADDS

 

IPv4 アドレスは、System.Versionと同じ体系([Major].[Minor].[Revision].[Build])なので、こいつにキャストすれば意図した順番に sort 出来ます。

キャストする場合は、スクリプトブロックで記述します。

 

# IPv4 アドレス sort
sort {[System.Version]$_.IPAddress}

 

PS C:\Temp> $CSVData | sort {[System.Version]$_.IPAddress} | ft * -AutoSize

HostName  IPAddress    CNAME                Role
--------  ---------    -----                ----
a03429-ap 10.20.2.116  Project001-deploy002 DPL
a06513-ap 10.20.42.93  Project001-bt003     BT
a06628-ap 10.20.42.94  Project001-bt004     BT
a04813-ap 10.20.42.101 Project001-ap001     AP-A
a04812-ap 10.20.42.102 Project001-ap002     AP-A
a05029-ap 10.20.42.103 Project001-ap003     AP-A
a05028-ap 10.20.42.104 Project001-ap004     AP-A
a04811-ap 10.20.42.121 Project001-ap021     AP-B
a04810-ap 10.20.42.122 Project001-ap022     AP-B
a04927-ap 10.20.42.124 Project001-ap024     AP-B
a05023-ap 10.20.42.125 Project001-ap025     AP-B
a05022-ap 10.20.42.126 Project001-ap026     AP-B
a05021-ap 10.20.42.127 Project001-ap027     AP-B
a05020-ap 10.20.42.128 Project001-ap028     AP-B
a05019-ap 10.20.42.129 Project001-ap029     AP-B
a05018-ap 10.20.42.130 Project001-ap030     AP-B
a05017-ap 10.20.42.131 Project001-ap031     AP-B
a05125-ap 10.20.42.133 Project001-ap033     AP-B
a06514-ap 10.20.42.193 Project001-admin003  ADMIN
a06629-ap 10.20.42.194 Project001-admin004  ADMIN
a04804-db 10.20.42.201 Project001-db001     DB
a04802-db 10.20.42.202 Project001-db002     DB
a04904-db 10.20.42.211 Project001-db011     DB
a04902-db 10.20.42.212 Project001-db012     DB
a06512-ap 172.18.42.53 Project001-domain003 ADDS
a06627-ap 172.18.42.54 Project001-domain004 ADDS

 

数字 sort

スクリプトの中で扱っている数値であれば、数値属性になっているのでそののまま sort しても問題はないのですが、CSV を読み込んだデーターの場合は、数値ではなく数字文字列になっています。

このため、数値だと思って sort すると IP アドレスと同様に残念な結果になります。

これを避けるには、数値にキャストして sort します。

# 数字文字列 sort
sort {[int]$_.Index}

 

ソート済みのオブジェクトを CSV に出力

最後にソート済みのオブジェクトを CSV に出力すれば処理完了ですね。

# sort
$SortData = $CSVData | sort {[Version]$_.IPAddress}

# CSV 出力
$SortData | Export-Csv .\SortHostRole.csv

 

関連情報

PowerShellのSort-ObjectコマンドレットでIPアドレスのソートを行う - 素敵なおひげですね
http://stknohg.hatenablog.jp/entry/2017/02/15/230954

オブジェクトをユニークにして存在数を付加する PowerShell フィルター
http://www.vwnet.jp/Windows/PowerShell/2016092401/CountUnique.htm

 

 

back.gif (1980 バイト)

home.gif (1907 バイト)

Copyright © MURA All rights reserved.