スクリプトの作成
PowerShell ワンライナーの記述からスクリプトの記述に移行すると、より複雑に聞こえます。 スクリプトは、.ps1
ファイルとして保存する以外は、PowerShell コンソールで対話形式で実行するのと同じコマンドまたは同様のコマンドに過ぎない。
foreach
コマンドレットの代わりに ForEach-Object
ループなど、使用できるスクリプトコンストラクトがいくつかあります。 この違いは、foreach
が言語キーワードと ForEach-Object
コマンドレットのエイリアスの両方であることを考慮すると、初心者にとって混乱を招く可能性があります。
ループ
PowerShell の最適な側面の 1 つは、そのスケーラビリティです。 1 つのアイテムに対してタスクを実行する方法を学習したら、同じアクションを数百の項目に適用するのとほぼ同じ簡単な方法です。 PowerShell でさまざまな種類のループのいずれかを使用して、項目をループ処理します。
ForEach-Object
ForEach-Object
は、PowerShell ワンライナーなど、パイプライン内の項目を反復処理するためのコマンドレットです。
ForEach-Object
は、パイプラインを介してオブジェクトをストリーミングします。
モジュールGet-Command
のパラメーターは複数の文字列値を受け入れますが、プロパティ名によるパイプライン入力でのみ受け入れます。 次のシナリオでは、Get-Command
パラメーターで使用するために する 2 つの文字列値をパイプする場合は、ForEach-Object
コマンドレットを使用する必要があります。
'ActiveDirectory', 'SQLServer' |
ForEach-Object {Get-Command -Module $_} |
Group-Object -Property ModuleName -NoElement |
Sort-Object -Property Count -Descending
Count Name
----- ----
147 ActiveDirectory
82 SqlServer
前の例では、$_
は現在のオブジェクトです。 PowerShell バージョン 3.0 以降では、$PSItem
の代わりに $_
を使用できます。 ほとんどの経験豊富な PowerShell ユーザーは、下位互換性があり、入力が少ないため、$_
を使用することを好みます。
foreach
キーワードを使用する場合は、アイテムを反復処理する前にメモリに格納する必要があります。操作している項目の数がわからない場合は困難な場合があります。
$ComputerName = 'DC01', 'WEB01'
foreach ($Computer in $ComputerName) {
Get-ADComputer -Identity $Computer
}
DistinguishedName : CN=DC01,OU=Domain Controllers,DC=mikefrobbins,DC=com
DNSHostName : dc01.mikefrobbins.com
Enabled : True
Name : DC01
ObjectClass : computer
ObjectGUID : c38da20c-a484-469d-ba4c-bab3fb71ae8e
SamAccountName : DC01$
SID : S-1-5-21-2989741381-570885089-3319121794-1001
UserPrincipalName :
DistinguishedName : CN=WEB01,CN=Computers,DC=mikefrobbins,DC=com
DNSHostName : web01.mikefrobbins.com
Enabled : True
Name : WEB01
ObjectClass : computer
ObjectGUID : 33aa530e-1e31-40d8-8c78-76a18b673c33
SamAccountName : WEB01$
SID : S-1-5-21-2989741381-570885089-3319121794-1107
UserPrincipalName :
多くの場合、foreach
や ForEach-Object
などのループが必要です。 それ以外の場合は、エラー メッセージが表示されます。
Get-ADComputer -Identity 'DC01', 'WEB01'
Get-ADComputer : Cannot convert 'System.Object[]' to the type
'Microsoft.ActiveDirectory.Management.ADComputer' required by parameter
'Identity'. Specified method is not supported.
At line:1 char:26
+ Get-ADComputer -Identity 'DC01', 'WEB01'
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-ADComputer], Parame
terBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.ActiveDirecto
ry.Management.Commands.GetADComputer
それ以外の場合は、ループを排除しながら同じ結果を得ることができます。 オプションを理解するには、コマンドレットのヘルプを参照してください。
'DC01', 'WEB01' | Get-ADComputer
DistinguishedName : CN=DC01,OU=Domain Controllers,DC=mikefrobbins,DC=com
DNSHostName : dc01.mikefrobbins.com
Enabled : True
Name : DC01
ObjectClass : computer
ObjectGUID : c38da20c-a484-469d-ba4c-bab3fb71ae8e
SamAccountName : DC01$
SID : S-1-5-21-2989741381-570885089-3319121794-1001
UserPrincipalName :
DistinguishedName : CN=WEB01,CN=Computers,DC=mikefrobbins,DC=com
DNSHostName : web01.mikefrobbins.com
Enabled : True
Name : WEB01
ObjectClass : computer
ObjectGUID : 33aa530e-1e31-40d8-8c78-76a18b673c33
SamAccountName : WEB01$
SID : S-1-5-21-2989741381-570885089-3319121794-1107
UserPrincipalName :
前の例でわかるように、 の Get-ADComputer
パラメーターは、パラメーター入力を使用して指定した場合にのみ 1 つの値を受け入れます。 ただし、パイプラインを使用すると、値が一度に 1 つずつ処理されるため、複数の値をコマンドに送信できます。
対して
指定した条件が true である間、for
ループが反復処理されます。 私は頻繁に for
ループを使用しませんが、用途があります。
for ($i = 1; $i -lt 5; $i++) {
Write-Output "Sleeping for $i seconds"
Start-Sleep -Seconds $i
}
Sleeping for 1 seconds
Sleeping for 2 seconds
Sleeping for 3 seconds
Sleeping for 4 seconds
前の例では、ループは数値 1 から始まり、カウンター変数 $i
が 5 未満である限り続行することで、4 回繰り返されます。 合計 10 秒間スリープ状態になります。
推奨
PowerShell には、do
と do until
の 2 つの異なる do while
ループがあります。
do until
は、指定した条件が false になるまで実行されます。
次の例は、推測した値が、Get-Random
コマンドレットによって生成されたのと同じ数値になるまで続く数値ゲームです。
$number = Get-Random -Minimum 1 -Maximum 10
do {
$guess = Read-Host -Prompt "What's your guess?"
if ($guess -lt $number) {
Write-Output 'Too low!'
} elseif ($guess -gt $number) {
Write-Output 'Too high!'
}
}
until ($guess -eq $number)
What's your guess?: 1
Too low!
What's your guess?: 2
Too low!
What's your guess?: 3
Do While
は反対です。 指定した条件が true と評価されている限り実行されます。
$number = Get-Random -Minimum 1 -Maximum 10
do {
$guess = Read-Host -Prompt "What's your guess?"
if ($guess -lt $number) {
Write-Output 'Too low!'
} elseif ($guess -gt $number) {
Write-Output 'Too high!'
}
}
while ($guess -ne $number)
What's your guess?: 1
Too low!
What's your guess?: 2
Too low!
What's your guess?: 3
Too low!
What's your guess?: 4
Do While
ループでテスト条件を「等しくない」に逆にすることで、同じ結果が得られます。
do
ループは常に少なくとも 1 回実行されます。これは、ループの終了時に条件が評価されるためです。
つつ
do while
ループと同様に、指定した条件が true である限り、while
ループが実行されます。 ただし、違いは、コードを実行する前に、while
ループがループの先頭にある条件を評価することです。 そのため、条件が false と評価された場合は実行されません。
次の例では、米国で感謝祭が行われる日を計算します。 常に 11 月の第 4 木曜日です。 ループは 11 月 22 日から始まり、1 日を追加しますが、曜日は木曜日と等しくありません。 22 日が木曜日の場合、ループはまったく実行されません。
$date = Get-Date -Date 'November 22'
while ($date.DayOfWeek -ne 'Thursday') {
$date = $date.AddDays(1)
}
Write-Output $date
Thursday, November 23, 2017 12:00:00 AM
break、continue、return
break
キーワードはループを終了するように設計されており、多くの場合、switch
ステートメントで使用されます。 次の例では、break
によって、最初のイテレーションの後にループが終了します。
for ($i = 1; $i -lt 5; $i++) {
Write-Output "Sleeping for $i seconds"
Start-Sleep -Seconds $i
break
}
Sleeping for 1 seconds
continue
キーワードは、ループの次の反復にスキップするように設計されています。
次の例では、数値 1、2、4、5 を出力します。 数値 3 をスキップし、ループの次の反復を続行します。
break
と同様に、continue
現在のイテレーションのみを除き、ループから抜け出します。 ループから抜け出して停止する代わりに、次のイテレーションで実行が続行されます。
while ($i -lt 5) {
$i += 1
if ($i -eq 3) {
continue
}
Write-Output $i
}
1
2
4
5
return
キーワードは、既存のスコープから抜け出すために設計されています。
次の例では、return
が最初の結果を出力し、ループから抜け出していることに注意してください。
$number = 1..10
foreach ($n in $number) {
if ($n -ge 4) {
return $n
}
}
4
結果文のより詳細な説明は、私のブログ記事「PowerShellのreturnキーワード」で見つけることができます。
概要
この章では、PowerShell に存在するさまざまな種類のループについて学習しました。
レビュー
-
ForEach-Object
コマンドレットとforeach
ステートメントの違いは何ですか? -
while
ループやdo while
ループの代わりにdo until
ループを使用する主な利点は何ですか? -
break
ステートメントとcontinue
ステートメントの違い
関連情報
PowerShell