Foreach-PowerShellの詳細

第19.3章 Foreachの設計、適用方法について説明します。



この構造には、ForEach-Objectコマンドレットと同じ目標があります。 ForEach-ObjectコマンドレットにはForEachエイリアスがあります。これは、ForEach演算子と完全に同じ名前であるため混同しやすい...です。 PowerShellはコンテキストを調べて、現在使用されているForeachを見つけます。 演算子とコマンドレットが同じことを行う方法の例を次に示します

Get-Service –name B* | ForEach { $_.Pause() } $services = Get-Service –name B* ForEach ($service in $services) { $service.Pause() }
      
      







このForeachステートメントがどのように機能するかを見てみましょう。括弧で囲まれた2つの変数がinキーワードで区切られています。 2番目の変数には、何かをしたい1つ以上のオブジェクトが含まれることが期待されます。 内部使用のための最初の変数は、2番目の変数からのオブジェクトを各パスに順番に格納します。 VBScriptで記述した場合、この種のことはおなじみのはずです。



2番目の変数には複数形を、最初の変数には単数形を指定するのが一般的です。 これは慣例や標準では必要ありませんが、$ Rockvillにオブジェクトが含まれている場合、Foreach($ Fred in $ Rocvill)を記述できますが、PowerShellはこれを処理します。 しかし、変数の意図的な命名に固執すると、覚える必要が少なくなります。



PowerShellは、2番目の変数から1つのオブジェクトを自動的に取得し、ループの各パスの最初のオブジェクトに配置します。 コンストラクト内では、最初の変数を使用してオブジェクトを処理できます。たとえば、このオブジェクトのPauseメソッドを呼び出すことができます。 コマンドレットで行うように、ステートメントでは$ _(またはPSItem)を使用しないでください。



場合によっては、使用するデザイン(演算子またはコマンドレット)がわからないことがあります。 理論的には、Foreachオブジェクトへのパイプは、状況によっては使用するメモリが少なくなる場合があります。 私たちの観察によると、コマンドレットはオブジェクトの大きなセットで実行が遅くなります。 パイプラインに複雑な処理がある場合、特にForeachステートメントがForeachコマンドレット内で処理されている場合は、フルネームを使用して、何が使用されているかを一意に判断することをお勧めします。



また、別のコマンドレットまたは関数にパイプライン転送を行う場合も注意する必要があります。 例

 PS C:\> foreach ($service in $services) { >> $service | select Name,DisplayName,Status >> } | Sort Status >> An empty pipe element is not allowed. At line:3 char:4 + } | <<<< Sort Status + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : EmptyPipeElement
      
      





PowerShellはパイプラインをさらに下に渡してソートするものがないためエラーをスローしましたが、この例は機能します。

 PS C:\> $services | foreach { >> $_ | select Name,DisplayName,Status >> } | Sort Status >> Name DisplayName Status ---- ----------- ------ Browser Computer Browser Stopped BDESVC BitLocker Drive Encrypt... Stopped bthserv Bluetooth Support Service Running BFE Base Filtering Engine Running BITS Background Intelligent ... Running
      
      





別の要因は、オブジェクトのコレクションを再度使用する必要があるかどうかです。さらにコレクションが必要な場合は、データを再度受信しないように演算子を使用することをお勧めします。 最後のポイントは、インターネットで見つけるスクリプトの多くは実際にはVBScript変換スクリプトであり、その中のオブジェクトのコレクションを常にソートする必要があるということです。 したがって、常に停止し、少しの間考えて、最適なアプローチと、コレクションを整理する必要があるかどうかを判断することをお勧めします。



アドバイス-これができない場合は、つぶしを使用しないでください。 たとえば、以前に指定したコードを別の方法で書き直します。

 Get-Service –name B* | Suspend-Service
      
      





ソートの例は、次のように記述すればより良く見えるでしょう。

 Get-Service b* | Sort Status | select Name,DisplayName,Status
      
      





何かのためにすべてのオブジェクトをソートする必要がない場合は、これを行わないでください。 Foreachコマンドレットまたはステートメントの使用は、実行すべきでないことを実行していることを示している場合があります。 これはすべての場合に当てはまることは確かですが、PowerShellが作業の一部を実行できるかどうかを検討してください。 この問題にこだわらないでください。多くのコマンドレットは、必要なパラメーターのアセンブリラインからの出力を受け入れないため、Foreachを使用することが必要になります。 何かを書いたのを正しくまたは誤って追跡するよりも、ジョブを終了することが重要です。

翻訳者挿入

これは、コンベア上のオブジェクトのパラメータをパラメータ名で結合するposikの機能を指します。 「パラメーターバインド」のプロセスで送信がオブジェクトのパラメーターを一意に識別できない可能性がある場合は、オブジェクトを一度に1つずつ並べ替える必要があります。 たとえば、WMI。 一般的な推奨事項-パイプライン処理を使用します。通常、サイクルはパイプラインを中断し、時には不必要な反復につながります。 たとえば、Foreach内で処理する場合よりも、Selectを実行してから処理する方が効率的です。



かっこを思い出すのに良い点です。 Foreach演算子には2つの変数が必要だと言ったときに嘘をつきました。 技術的な観点からは、このために必要な変数は1つだけです。 2番目のオブジェクトには、前の例のように変数に入れることができるオブジェクトのコレクションを含めるか、かっこで囲んだ式の結果にすることができます。次に例を示します。

 foreach ($service in (Get-Service –name B*)) { $service.pause() }
      
      





このバージョンは読みにくいですが、絶対に合法であるため、中間結果を変数に保存する必要はありません。 内部ブラケットが最初に計算され、渡されるオブジェクトのコレクションを生成します。



All Articles