Where-Object :行の選択、オブジェクトの選択、SQLのWhere句
Where-Object で絞り込む
Powershellのコマンド結果はオブジェクト形式で返却されることが多いが、
そのオブジェクト形式で返ってきた結果の一部だけを取得する方法の実験。
例えば、以下のようなコマンドレットを実行すると、結果がズラズラと表示される。
これらの1行の情報はオブジェクトのデータを表示している。
> Get-ChildItem Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2020/09/21 9:33 .android d----- 2020/09/20 22:39 .AndroidStudio4.0 d----- 2018/04/21 22:26 .gimp-2.8 ・・・ -a---- 2021/06/15 18:03 761 _gvimrc -a---- 2021/06/17 20:04 9117 _viminfo -a---- 2021/06/16 17:39 3542 _vimrc
なので、例えば$aにコマンドレットの結果をオブジェクトの配列として格納して、インデックスでアクセスできる。
> $a = Get-ChildItem > $a[0] Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2020/09/21 9:33 .android > $a[0].Name .android
そうすると、例えば、Nameがドット(.)から始まるフォルダ、ファイルの情報だけが欲しい・・・なんてことはよくある。
目次
本文
1. Where-Objectで行選択
Where-Objectコマンドレッドにより任意の条件に合致するオブジェクトだけを絞り込むことができる。 誤解を恐れずイメージだけで言えば、Where-Objectは行選択できる。
例えば、Nameが”.android"の行だけに絞り込みたいなら、こんな感じ。
> Get-ChildItem | Where-Object { $_.Name -eq ".android"} Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2020/09/21 9:33 .android
Where-Objectの基本形はこれだけ。
2. 比較演算子
ここら辺の比較演算子は、if文を使うときには必ず通ることなので、特に記すべきこともないが、
-likeと-matchだけ深堀りしようと思う。
3. 比較演算子 -like (ワイルドカードを使った比較)
ワイルドカードを使った、簡単な条件指定ができる。
ワイルドカード | 説明 | 例 | True | False | 備考 |
---|---|---|---|---|---|
* | 0個以上の文字と一致 | a* | a、ab、Apple | ba、bab、BApple | 先頭末尾という概念はあり |
? | 指定位置の1文字と一致 | a? | ab、Ap | ba、abb、a | まず文字数が一致しないとダメ |
[ ] | 指定範囲の1文字と一致 | a[a-c]c | aac、abc、acc、aAc | ac、adc | 文字数一致と範囲の1文字と一致 |
[ ] | 指定された1文字と一致 | a[rkq]c | arc、akc、aqc、aRc | ac、aac | 文字数一致と列挙の1文字と一致 |
※[]内にワイルドカード(*,?)は使えない。記述してもリテラルとして解釈されるようだ。
4. 比較演算子 -match (正規表現を使った比較)
以下、再検証
形式 | 説明 | 例(パターン) | True | False | 備考 |
---|---|---|---|---|---|
値 | 値が(部分的に)一致すればTrue | "bc" | "abcd"、"bcd"、"abc" | "adc" | 部分一致すればTrue |
. | 任意の 1 文字と一致すればTrue | "a..d" | "abcd"、"abcdz"、"zabcd" | "abd"、"abcz" | ワイルドカードの?に似ている |
[ ] | カギ括弧内の1 文字と一致すればTrue | "a[abcdefg]c" | "abc"、"agc" | "ahc"、"ac"、"abz" | |
[ ] | カギ括弧内の範囲の1 文字と一致すればTrue | "a[a-g]c" | "abc"、"agc" | "ahc"、"ac"、"abz" | |
[^] | カギ括弧内の文字以外の任意の文字と一致すればTrue | "a[^abc]c" | "adc" | "aac"、"abc"、"acc"、"adz" | |
^ | 先頭を表す | "^ab" | "ab"、"abc" | "bb"、"bbc"、"ac" | |
$ | 末尾を表す | "yz$" | "yz"、"xyz" | "yy"、"xyy"、"xz" | |
* | 先行する文字が0個以上 | "a*c" | "ac"、"aac"、"aaac"、"abc"、"c" | ”a”、”aa"、”aad" | 部分一致でTrueになる原則、は直前文字が0個以上。 その為”ac”は実質cが一文字でもあればTrue |
? | 先行する文字が1 個以上(だと思う) | "a?c" | "c"、"ac" | ""、"a"、"d" | 分からん・・・バグってないか? |
同上 | 同上 | "a?" | ""、"c"、"z"、"zzz" | (なし) | 何にでもマッチするぞ・・・ |
\ | 後続文字をエスケープ(リテラル化) | "a\?" | "a?"、"a?b" | "c?"、"a!" | ?がリテラルとして処理される |
- 上記は、大文字、小文字は区別しない
- 日本語もOK
5. Where-ObjectってForEach-Objectでもできるんじゃね?
ふと思ったので、試してみたらできた。まあ、好きな方を使えばいいんじゃないかな。
> Get-Childitem | ForEach-Object{ if($_.Name -eq ".android"){$_}} Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 2020/09/21 9:33 .android
バージョン情報
> $PSVersionTable Name Value ---- ----- PSVersion 5.1.19041.1023