この記事をシェアする

Windows PowerShellで使えるgrep的なコマンドレット「Select-String」とパイプラインを組み合わせたところなんかうまくいかなかったが間に「Out-String -Stream」を挟むことで何とかなった

結論

#良い書き方
Select-String "二宮飛鳥" .\idol.txt -Context 0,3 | Out-String -Stream | Select-String "身長","血液型"

##もしくは
Select-String "二宮飛鳥" .\idol.txt -Context 0,3 | oss | Select-String "身長","血液型"

#悪い書き方
Select-String "二宮飛鳥" .\idol.txt -Context 0,3 | Select-String "身長","血液型"

余談

例えば、こんな感じのテキストファイルがあったとする。

名前:二宮飛鳥
身長:154cm
体重:42kg
血液型:B型

名前:南条光
身長:140cm
体重:41kg
血液型:B型

…

で、「二宮飛鳥」の身長と血液型を抽出したい、ってなったとき、grep(つーかUNIX系のシェル)ならこういう風に書ける。

grep -A 3 "二宮飛鳥" idol.txt | grep -e "身長" -e "血液型"
コマンドの実行結果

で、このgrepと同じようなコマンドはWindow PowerShellにも用意されている。それが件名にもあるSelect-Stringである。記法やオプションは違うが、大体grepと同じようなことができるようだ。これでgrepのためだけにGit Bash入れなくて済むよ! やったねモバP!

でまあ、grepと同じように使えるのであれば、以下のようにパイプラインで繋ぐことで絞り込み検索できるもんだと思ってやってみた訳なんですよ。

Select-String "二宮飛鳥" .\idol.txt -Context 0,3 | Select-String "身長","血液型"
しかしながらこれが現実

…あれ?

どうにもPowerShellのパイプラインでコマンドとコマンドを繋ぐと、繋いだ先のコマンドにはコンソール上に表示されるテキストではなく、コマンドを実行した結果生成されるオブジェクトが渡されるそう。そんなわけで、単純にUNIX系のパイプラインと同じように使うことはできないんだと。へえ。

じゃあUNIXとかのパイプラインと同じことしたい時はどうするの?
って訳なんだけども。そこで登場するのが、「Out-String -Stream」ってわけ。

これを先程のSelect-StringとSelect-Stringの間にパイプライン使ってぶちこむ。

Select-String "二宮飛鳥" .\idol.txt -Context 0,3 | Out-String -Stream | Select-String "身長","血液型"

こいつを実行すると…

grepと大体同じような結果が得られる

Out-Stringは受け取ったオブジェクトを文字列に変換するコマンドとのこと。つまりこいつをSelect-StringとSelect-Stringの間に差し込むことで、二回目のSelect-Stringに一回目のSelect-Stringの実行結果がテキストとして渡される…って認識でよいのだろうか?

ちなみに、「Out-String -Stream」には「oss」という短縮記法が用意されており、以下のようにも書けるそう。

Select-String "二宮飛鳥" .\idol.txt -Context 0,3 | oss | Select-String "身長","血液型"
当然だけど得られる結果は同じ
この記事をシェアする