tech.guitarrapc.cóm

Technical updates

PowerShellのSelect-Objectを使って任意の個数毎にObjectを取り出す

最近ようやく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

注意

牟田口先生から、二重ループになるので爆発する可能性を指摘されたので、小さい数専用で。 次の記事で、修正したバージョンを上げます。