PowerShellのオブジェクトのコレクションでプロパティの値を操作する際には、必要のないものをフィルタリングする方法が必要になることがあります。PowerShellのWhere-Object
コマンドレットの使用方法を知っておくことは、PowerShellのツールボックスにおいて重要なスキルです。
Where-Object
コマンドレットは、オブジェクトをフィルタリングする便利な方法です。このチュートリアルでは、Where-Object
コマンドの構築方法、利用可能なパラメータ、構文、および複数の条件を使った効果的な使用方法について学びます。
前提条件
この記事の前提条件は1つだけです。PowerShellのコマンドと構文について基本的な理解がある必要があります。
この記事のすべての例は、現行の安定版のPowerShell(執筆時点でのバージョン7.1.0)を基にしています。ただし、Windows PowerShell 4.0以降があれば、コマンドは同じように動作します。
PowerShellのWhere-Objectの動作の理解
PowerShellのWhere-Object
コマンドの唯一の目的は、コマンドの出力をフィルタリングして必要な情報のみを返すことです。
要するに、Where-Object
コマンドレットはフィルターです。条件を構築し、TrueまたはFalseを返すことができます。その条件の結果に応じて、コマンドレットは出力を返すかどうかを決定します。
その条件は2つの方法のいずれかで作成できます。「古い」方法では、スクリプトブロックを使用し、「新しい」方法ではパラメータや比較文を使用します。
スクリプトブロックを使用したフィルタ条件の作成
スクリプトブロックは、PowerShellの重要なコンポーネントです。スクリプトブロックは、言語全体で何百もの場所で使用されます。スクリプトブロックは無名の関数です。コードを区分して異なる場所で実行する方法です。スクリプトブロックを使用して、Where-Object
のフィルタを作成することができます。
フィルタとしてスクリプトブロックを使用するには、FilterScript
パラメータを使用します。このパラメータを使用して、FilterScript
パラメータにスクリプトブロックを作成して渡すことができます。
スクリプトブロックがブール値のFalseまたはnull以外の値を返す場合、Trueと見なされます。それ以外の場合はFalseと見なされます。
例えば、現在の起動タイプがAutomaticのWindowsサービスをすべて検索する必要があるとします。まずGet-Service
を使用して現在のすべてのサービスを取得します。Get-Service
は、さまざまなプロパティを持つさまざまなサービスオブジェクトを返します。
PowerShell パイプラインを使用すると、オブジェクトを Where-Object
コマンドレットにパイプすることができます。その際、FilterScript
パラメータにスクリプトブロックを指定することができます。以下のように、各オブジェクトの StartType
プロパティが Automatic と等しいかどうかを確認する条件を作成できます。
フィルタリングのスクリプトブロックを作成したら、そのスクリプトブロックを FilterScript
パラメータに指定します。Where-Object
はパイプラインで渡されるすべてのオブジェクトに対してそのスクリプトブロックを実行し、各 StartType
プロパティを評価します。プロパティが Automatic と等しい場合、Where-Object
はオブジェクトを通過させます。そうでない場合、オブジェクトは破棄されます。
以下に、この方法の簡単な例を示します。

多くの人々は、
Where-Object
コマンドレットで位置パラメータを使用し、FilterScript
パラメータ名を含めません。代わりに、スクリプトブロックだけを提供します。例:Where-Object {$_.StartType -eq 'Automatic'}
。
このような構成は、この特定のシナリオでは機能しますが、スクリプトブロックの中括弧や パイプライン変数 $_
は、コードの可読性を低下させ、経験の浅い PowerShell ユーザーにとっても理解しにくくなります。この可読性の問題が、PowerShell チームがパラメータや比較文を導入した理由です。
比較文
Windows PowerShell 3.0で導入された比較文は、構築方法によりより自然なフローを持っています。前の例と同じシナリオを使用して、比較文の構文を使用して、自動起動タイプのすべてのWindowsサービスを検索しましょう。
上記の例では、スクリプトブロックの代わりに、コマンドはオブジェクトのプロパティをProperty
パラメータの値として指定しています。eq
演算子もパラメータとして使用され、Automaticの値を渡すことができます。
このようにパラメータを使用することで、スクリプトブロックの必要性が完全になくなります。
A scriptblock is a better choice when defining more complex filtering conditions. The
Property
parameter may not always be the best choice. If using a scriptblock, just remember to document your code using comments!
次のセクションでは、Where-Object
で使用できる利用可能な比較演算子の種類について学びます。
フィルタリングの基本
パラメータを使用して、Where-Object
は一般的な比較演算子を使用してオブジェクトのコレクションをフィルタリングします。いくつかの例を見てみましょう。
包含演算子
包含演算子は、コレクションを扱う際に便利です。包含演算子を使用すると、コレクションが特定の項目を含んでいるかどうかを条件として定義できます。
例えば、コレクション内の特定のプロパティ値をフィルタリングしたい場合、包含演算子を使用することができます。
PowerShellでは、いくつかの異なる包含演算子が用意されています:
-contains
/-ccontains
– プロパティ値を含むコレクションをフィルタリングします。-notcontains
/-cnotcontains
– プロパティの値を含まないコレクションをフィルタリングします。-in
/-cin
– 値がコレクション内にある場合、一致するプロパティの値を返します。-notin
/-cnotin
– 値がコレクション内にない場合、プロパティの値がない場合はnull
/$false
を返します。
大文字と小文字を区別する場合は、-c[operator]
で始まる包含演算子を使用してください。
関連記事: PowerShell比較演算子の理解(例による)
たとえば、BITS Windowsサービスの状態を確認したい場合、以下のようにcontains
パラメータ(演算子)を使用してBITSの値を渡すことができます。
そして、以下が予想される結果です:

常に左側をフィルタリングすることを忘れないでください!前の例は、
Get-Service -ServiceName 'BITS'
を実行するのと同じです。
もっと洗練された方法で、StatusがRunningではなく、かつStartTypeがinという単一の文字列(または配列)Manualのすべてのサービスを検索したい場合、以下のスクリプトブロックを使用して、コマンドはこれらの条件の両方を評価するためにFilterScript
パラメータを使用しています。
関連記事: 基礎に戻る:PowerShellオブジェクトの理解
上記のコマンドを実行すると、停止しているサービスのみが表示され、StartTypeがManualのものが表示されます。

コレクション内の多くのプロパティ値を含むフィルタリングには、含有演算子を組み合わせることで効果的に行うことができます。 Get-Service
が返すプロパティの数を考慮すると、含有演算子と論理演算子を組み合わせることで、これらのプロパティをフィルタリングすることが容易になります。
マッチング演算子
Where-Object
で含有演算子を使用する方法と同様に、マッチング演算子も使用することができます。マッチング演算子を使用すると、文字列内の文字列を一致させることができます。 例えば、'foofoo' -like '*foo*'
はTrueを返し、'foofoo' -match 'foo'
もTrueを返します。マッチング演算子は、文字列の一致を確認します。文字列内の
PowerShellでは、Where-Object
内で使用できるさまざまなマッチング演算子があります。
-like
/-clike
– 文字列がワイルドカードパターンに一致します。-notlike
/-cnotlike
– 文字列がワイルドカードパターンに一致しません。-match
/-cmatch
– 文字列が正規表現パターンに一致します。-notmatch
/-cnotmatch
– 文字列が正規表現パターンに一致しません。
大文字と小文字を区別する場合は、
-c[operator]
で始まるマッチング演算子を使用してください。
コンテンツオペレーターとほぼ同じ形式で、以下に示すように、マッチングオペレーターを使用することができます。以下の例では、DisplayNameプロパティの値にWindowsが含まれるすべてのサービスを検索しています。

match
operator uses regular expressions to match on certain values.関連: PowerShellと正規表現の初め方
また、like
オペレーターを使用して、ワイルドカード(*
)を使用して任意の文字に一致させるか、?
を使用して1つの文字に一致させるなど、一般的なマッチング技術を使用することもできます。
結果は、最初の3文字が「Win」であるサービス名に絞り込まれます。

ワイルドカードを使用することで、サービスのフルネームを知る必要はありません。文字列のいくつかの文字だけが必要です。これらのオペレーターは、フィルタリングをさらに強化するために、論理演算子と組み合わせることもできます。
等値演算子
コンテンツオペレーターや比較オペレーターの使用方法と同様に、Where-Object
で等値演算子も使用できます。等値演算子は、数値の比較が必要な場合に便利です。
例えば、1 -eq 1
はTrueですが、1 -gt 2
はFalseです。PowerShellにはさまざまな等値演算子があり、Where-Object
のパラメーターとしてまたは条件のスクリプトブロック内で使用できます。
-eq
/-ceq
– 指定した値に等しい値です。-ne
/-cne
– 指定された値と等しくない値。-gt
/-cgt
– 指定された値より大きい値。-ge
/-cge
– 指定された値以上の値。-lt
/-clt
– 指定された値より小さい値。-le
/-cle
– 指定された値以下の値。
たとえば、CPUの使用率が2%から10%の間の実行中のプロセスを検索したい場合、Get-Process
とWhere-Object
のPowerShellコマンドレットを使用することができます。
スクリプトブロックを使用して、2つの条件をand
演算子で組み合わせることができます。両方がTrueを返す場合、Where-Object
はパイプラインに渡されたプロセスオブジェクトを返します。少なくとも1つの条件がFalseを返す場合、Where-Object
はオブジェクトを破棄します。
以下は期待される結果です:

Where-Object
の等値演算子を使用してフィルタリングすることで、システムレポートの作成や値の比較に役立ちます。
次の手順
PowerShellのWhere-Object
コマンドレットを使用して、さまざまなものをフィルタリングする方法についてより詳しく理解したので、他に何ができるでしょうか? 複数の条件や演算子を使用してコレクションをフィルタリングし、プロパティの値を取り除き、出力を好みの形式に整形するために、より複雑なフィルタリングタスクを試してみてください。
Source:
https://adamtheautomator.com/powershell-where-object/