最近ようやくBash漬けからPowerShellな日々に戻れそうな戻れなさそうな予感です。
しばらくブログ更新すらできない状況でしたが再び活動再開したいなぁとか。
さて、今回は、あるObjectの集合から、任意の個数ごとにObjectを取り出す操作をPowerShellで考えてみます。
例えば、1~131の連番で、20個ずつ取り出してそれぞれを別々のファイルに保存したりとか、ありますよね?
意外とこういうの他で見かけないので、参考になれば幸いです。
利用するコマンドレット
結構癖があって面倒なこの子を使います。
Select-Object
Select-Object
には、skipパラメータとfirst(あるいはlast)パラメータがあります。
これを使えば.....簡単に実現できます。
サンプル
では例に上げた、1~131の連番になった配列から20個ずつ取り出す処理を見てみましょう。
$numbers = 1..131
$GroupNum = 20
$skipcount = [math]::Truncate($numbers.count / $GroupNum)
0..$skipcount | %{
$numbers | Select-Object -skip $($GroupNum*$_) -First $GroupNum
"--------------------------------------------"
}
結果表示です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--------------------------------------------
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
--------------------------------------------
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
--------------------------------------------
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
--------------------------------------------
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
--------------------------------------------
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
--------------------------------------------
121
122
123
124
125
126
127
128
129
130
131
--------------------------------------------
function化
実際私が利用したのはfilterですが、functionのサンプルを。
function Split-Object{
[CmdletBinding(
SupportsShouldProcess = $false,
ConfirmImpact = "none",
DefaultParameterSetName = ""
)]
param
(
[Parameter(
HelpMessage = "Input Object you want to split",
Position = 0,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
#[ValidateNotNullOrEmpty()]
[object[]]
$Item,
[Parameter(
HelpMessage = "Input Number you want to split each",
Position = 0,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[ValidateNotNullOrEmpty()]
[int]
$GroupNumber
)
begin
{
$skipcount = [math]::Truncate($Item.count / $GroupNumber)
}
process
{
0..$skipcount | %{
$Item | Select-Object -skip $($GroupNumber * $_) -First $GroupNumber
# {Set command you want to do...}
}
}
end
{
}
}
利用例
function Split-Object{
[CmdletBinding(
SupportsShouldProcess = $false,
ConfirmImpact = "none",
DefaultParameterSetName = ""
)]
param
(
[Parameter(
HelpMessage = "Input Object you want to split",
Position = 0,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
#[ValidateNotNullOrEmpty()]
[object[]]
$Item,
[Parameter(
HelpMessage = "Input Number you want to split each",
Position = 0,
Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true
)]
[ValidateNotNullOrEmpty()]
[int]
$GroupNumber
)
begin
{
$skipcount = [math]::Truncate($Item.count / $GroupNumber)
}
process
{
0..$skipcount | %{
$Item | Select-Object -skip $($GroupNumber * $_) -First $GroupNumber
# {Set command you want to do...}
}
}
end
{
}
}
Split-Object -Item $(ps | sort WS -Descending) -GroupNumber 20
-ItemパラメータにGet-Process (Aliasがps) を渡してあげると、20ずつ--------------を引くようにしています。
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
584 65 478508 374236 747 1,931.87 6264 opera
1314 123 185840 250584 1139 231.46 3784 ScriptEditor
1985 76 235516 214536 529 912 svchost
1144 162 130628 189628 574 54.94 7504 iexplore
1795 683 80344 113528 919 100.15 3560 explorer
825 83 54864 94664 407 58.64 5620 iexplore
483 85 114280 92688 281 2016 MsMpEng
988 68 114768 75384 482 1,748.68 6736 GOM
239 29 52524 62728 294 976 dwm
607 41 65596 49848 225 396.85 4108 Skype
866 97 25040 47800 364 7.57 2908 explorer
623 41 12888 37312 239 2.14 8260 iexplore
1088 44 40916 27492 146 372 svchost
290 26 13728 26684 164 0.19 5244 WWAHost
316 278 9648 25704 652 2.75 3592 taskhostex
2583 88 142464 24212 628 55.97 1908 holLaunchPadOnline
177 13 13292 21716 198 4.96 3616 ImeBroker
778 38 16136 21068 117 988 svchost
103 9 21200 20388 117 18.05 4708 Everything-1.2.1.421b
477 41 24752 20088 399 1356 svchost
--------------
845 33 21088 20000 128 884 svchost
240 25 21904 17324 211 24.63 3536 RaUI
930 79 19184 16684 1539 1152 svchost
385 31 10396 16100 166 3.28 4804 clover
647 44 11800 15512 145 3.76 3272 SkyDrive
466 29 3104 14932 258 536 csrss
513 29 10040 13960 95 1688 svchost
1171 28 10452 13084 62 628 lsass
342 18 7956 13016 85 1116 dasHost
492 55 41520 11576 716 7.21 5012 mmc
400 43 10772 11456 960 4260 svchost
611 53 30008 10072 660 4076 SearchIndexer
138 12 2768 8036 104 0.02 4584 FlashUtil_ActiveX
532 16 7384 7952 44 772 svchost
118 10 8380 7824 41 36.82 5736 audiodg
287 13 7388 7332 36 612 services
102 8 1800 6700 73 0.02 7616 RuntimeBroker
370 20 4084 6512 95 0.56 800 jusched
390 15 4536 5948 46 732 svchost
253 21 6164 5820 133 8.27 1080 SetPoint
--------------
820 94 82368 5688 881 16.35 4412 CCC
101 8 1776 5592 32 9652 WmiPrvSE
298 34 27212 4400 586 0.34 5024 MOM
162 17 3728 3864 101 1.97 4596 IDM
119 11 2060 3848 61 1752 c2c_service
271 34 7288 3376 186 46.44 4516 MagicFormation
366 20 3800 3216 73 1328 spoolsv
88 7 1608 3188 34 6364 dllhost
277 19 8896 3068 408 0.05 6936 CSISYN~1
139 11 1872 3060 89 432 atieclxx
292 21 4056 2836 111 0.70 4052 KHALMNPR
447 14 2448 2712 68 436 csrss
254 17 6864 2644 97 2324 vmware-authd
140 11 2324 2512 44 1896 svchost
368 43 200276 2508 294 1640 sqlservr
351 18 19132 2496 173 10.64 1100 lightscreen
118 10 1808 2404 42 5204 wlanext
203 16 7160 2332 110 1568 IpOverUsbSvc
149 8 1728 2052 70 588 winlogon
148 12 2124 1988 71 2124 vmware-usbarbitrator64
--------------
137 14 3716 1656 46 1996 svchost
96 10 1428 1628 48 1936 vmnat
203 9 1416 1524 43 4840 WUDFHost
94 10 3416 1404 43 1472 svchost
211 10 1456 1388 43 3008 WUDFHost
81 7 1136 1376 67 0.02 1200 ZuneLauncher
146 14 2808 1316 75 1492 BingDesktopUpdater
79 9 1428 1188 43 1852 sqlwriter
100 6 800 988 25 840 atiesrxx
429 26 8324 892 103 4384 wmpnetwk
74 8 940 720 54 528 wininit
167 26 26360 700 514 3668 PresentationFontCache
36 2 292 548 5 316 smss
943 0 136 500 11 4 System
30 4 576 368 27 5228 conhost
50 7 1116 332 27 2056 vmnetdhcp
0 0 0 20 0 0 Idle
--------------
あるいは、1-10位まで、11-20位までなどのランキングも、この要領でサクッとできますね。
Groupnumを固定にしていますが、process{}内部で可変にすればいいかもしれません。
Select-Objectは厄介ですが、上手く使うと便利ですね。
GitHub
一応今回のサンプルを挙げておきますね
https://github.com/guitarrapc/PowerShellUtil/tree/master/Split-Object
注意
牟田口先生から、二重ループになるので爆発する可能性を指摘されたので、小さい数専用で。
次の記事で、修正したバージョンを上げます。