【ForEach-Object】PowerShellで配列の要素をループ処理させる方法

こんにちは。チェシャ男です。(-皿-)

今回は、

【PowerShell のループ処理方法】

についてご紹介します。

配列のようなコレクションオブジェクトに対してループ(繰り返し)処理をする場合は、”ForEach-Object” を使用します。

配列に自信がない方は、入門者用の配列講座をご用意していますのでこちら↓を是非ご覧ください。

[blogcard url=”https://cheshire-wara.com/powershell/ps-textbooks/basic-grammar/array-biginner1/”]

 

Foreach-Object でループ処理する

ループ処理を行うコマンドレットに

ForEach-Object

というものがあります。

[blogcard url=”https://cheshire-wara.com/powershell/ps-help/foreach-object-help/”]

【コマンドレット】

ForEach-Object

【オプション】

パターン1
[v2 まで] -Begin      <初期化スクリプトブロック{}>
-End       <終了スクリプトブロック{}>
-InputObject   <入力オブジェクト>
-Process     <適用スクリプトブロック{}>

[v3,v4,v5 以降] -Begin      <初期化スクリプトブロック{}>
-End       <終了スクリプトブロック{}>
-InputObject   <入力オブジェクト>
-Process     <適用スクリプトブロック{}>
-RemainingScripts <残りのスクリプトブロック{}>
-Confirm
-WhatIf

パターン2
-MemberName  <メンバー名>
-ArgumentList   <引数リスト>
-InputObject   <入力オブジェクト>
-Confirm
-WhatIf

【入力】

System.Management.Automation.PSObject

【出力】

System.Management.Automation.PSObject

【エイリアス】

ForEach
%

 配列に対して繰り返し処理を行う

ForEach-Object コマンドレットを使用した場合、オブジェクト(コレクション)内の各データに対しループ処理を行うことができます。

例えば、

$Array = @( 1, 2, 3, 4 ,5)

のような配列があったとします。
すべての要素に「+1」づつプラスしたい場合に、ループ処理を使わなければ、

$Array[0] = $Array[0] + 1
$Array[1] = $Array[1] + 1
.
.
.
$Array[4] = $Array[4] + 1

という風に同じような処理を何度も何度も書かなければなりません。

もし手書きの場合、配列の要素が数個ならいいですが何十個何百個となると考えるだけで恐ろしいですね。

そんな時は ForEach-Object コマンドレットを使用してループ処理をまとめてみましょう。

ForEach-Object コマンドレットでループ処理する場合はパイプラインを使ってオブジェクトを渡すことが多いです。

また実際の処理部分はスクリプトブロックと呼ばれる”{}(中かっこ)“で囲まれている必要があります。

-Process” オプションで指定した箇所がループ中のメイン処理部分になります。

実際にコマンドレットを実行してみましょう。

PS C:\> $array = @(1,2,3,4,5)

PS C:\> #ループ処理で1を足していく
PS C:\> $array | ForEach-Object -Process {$_ + 1}
2
3
4
5
6

このように配列オブジェクトをそのままパイプラインで渡してあげると、各要素を参照しすべてに「+1」の処理を実行してくれます。

ちなみに”$_”は自動変数といいパイプラインから渡されたデータ(オブジェクト)が格納されています。(上で言うと配列の各要素が順番に”$_”に代入されます)

このままでは画面に出力されて終わりなので”$Array“に戻してあげる処理を加えましょう

PS C:\> $array = @(1,2,3,4,5)

PS C:\> #配列を参照
PS C:\> $array
1
2
3
4
5

PS C:\> #ループ処理で1を足していく + $Arrayに格納する
PS C:\> $array = $array | ForEach-Object -Process {$_ + 1}

PS C:\> #配列を参照
PS C:\> $array
2
3
4
5
6

このように配列に対してパイプラインを駆使すると、”ForEach-Object” でループ処理ができます。

今回は配列を例に解説しましたが、他のコマンドレットの実行結果に対してループ処理することもできます。こちら↓の記事で解説していますので是非ご参考ください。

[blogcard url=”https://cheshire-wara.com/powershell/ps-cmdlets/object/foreach-object-cmdlets/”]

Foreach-Object は処理を加えるときに使え!

さて、突然ですが PowerShell というツーが非常に便利であることを思い出してください!

ここまで ForEach-Object の使い方をご紹介してきましたが、実はあまり意識をしなくても PowerShell は勝手にループ処理をしていてくれたんです。

例えば、

以下のような配列を宣言します。

$Array = @( 1 , “a” )

PowerShell の画面で $Array と入力してみましょう。

要素が画面に出力されましたが、これもループ処理なんです。

「配列の要素を順番に画面に表示する」という単純なループ処理です。

今回は簡単な例で説明しましたが、”VBscript” などの以前の Windows ツールでは出力するだけでも毎回 foreach を指定しなければならなかったんです。(便利になりましたね~)

では、どんな時に ForEach-Object を使うのかというと

ループ中に処理を加える時

です。

先ほど紹介したようにループしながら「配列の要素に数を足したり引いたりする」ときなんかに使います。ループ中に何かの操作を加えるかどうかがキーになってきます。

 Begin オプションと END オプション

冒頭で示したように ForEach-Object コマンドレットには「Beginオプション」と「Endオプション」があります。

初期化処理のような前処理をしていする場合は「-Begin」、処理の後最後に1回実行するような処理があれば「-End」を指定することができます。

Begin オプションで前処理する

Begin オプションを指定することで前処理をしてみましょう。Process オプションと同様に“{}(中かっこ)“で囲まれたスクリプトブロック内に処理を記載します。

今回は簡単に文字列出力をしてみましょう。

PS C:\> $array = @(1,2,3,4,5)
PS C:\>
PS C:\>
PS C:\> #ループ実行前に文字出力
PS C:\> $array | ForEach-Object -Begin {"Loopスタート"} -Process {$_ + 1}
Loopスタート
2
3
4
5
6

処理の最初に「Loopスタート」が出力されましたね!

Endオプションで出力する

次は End オプションで最後に処理を加えてみましょう。こちらも Process オプションと同様に”{}(中かっこ)“で囲まれたスクリプトブロック内に処理を記載します。

こちらも簡単な文字列出力を行います。

PS C:\> $array = @(1,2,3,4,5)
PS C:\>
PS C:\> #ループ実行後に文字出力
PS C:\> $array | ForEach-Object -Process {$_ + 1} -End {"Loopフィニッシュ"}
2
3
4
5
6
Loopフィニッシュ

 “-Begin” と “-End” を同時に使う

上で説明した “-Begin” と “-End” はもちろん同時に使用することができます。

PS C:\> $array = @(1,2,3,4,5)
PS C:\>
PS C:\> #前後にメッセージ出力
PS C:\> $array = $ar$array = $array | ForEach-Object -Begin {"Loopスタート"} -Process {$_ + 1} -End {"Loopフィニッシュ"}
PS C:\>
PS C:\> $array
Loopスタート
2
3
4
5
6
Loopフィニッシュ

このように、For-EachObject での処理順番は、

$array = $array | ForEach-Object -Begin {“前”} -Process {“メイン処理”} -End {“後”}

⑤代入 = ①パイプ渡し | ②前処理 ③メイン処理 ④後処理

という順番で処理します。変数の初期化処理が必要な場合などは前処理が活躍しますね。

 まとめ

オブジェクトに対してループ処理をしたいときは、

<オブジェクト> | ForEach-object -Process {<処理内容>}

を使用する。

前処理が必要な場合は、

-Begin {<前処理>}

後処理が必要な場合は、

-End {<後処理>}

エイリアスを使って簡単に書くと

<オブジェクト> | % {<処理内容>}

コメントを残す

メールアドレスが公開されることはありません。