プロジェクト

全般

プロフィール

PowerShellについて » 履歴 » バージョン 4

バージョン 3 (健二 酒井, 2019/03/11 21:26) → バージョン 4/7 (健二 酒井, 2019/03/11 21:28)

# PowerShellについて

## 概要

ボスがPowerShellで詰まっていたので自分なりの理解を説明するための記事
PowerShellを知らない人が以下の記事の「Code」を理解できるようになるのを目的にする:
PowerShell でウインドウの位置と大きさを指定
https://qiita.com/yumura_s/items/f6fa9dbeb5c6c4b6e4fb

## 読めない

独特な書き味があって知らないと辛いことが多い。
シェルスクリプトの一種だと意識すると読みやすくなるかも。(でも中身の仕組み的には結構違うっぽい(後述))
パイプを通して各コマンドにデータを一つずつ渡していくような考え方は近いと思う

### コツ

上記記事のコードの場合、以下を意識すると良いかな。

* 「fileter」は「function」と読み替える。実際、filterは特殊なfunctionでしかない。
* %はforeachと読む。パイプで渡された各オブジェクトに対し{}ブロック内の処理を実行する
* C#のコードは無視する。それでもやりたいことは分かる。
* 各コマンドはオブジェクトが渡され、オブジェクトを出力
* 変数やリテラルだけの行は「Write-Output 変数やリテラル」と読む。$rc2は「Write-Output $rc2」と読む。Write-Outputは後述。

上記記事に書かれている「Code」は関数の定義だけ書かれてる感じになる。 なので上記記事に書かれている「Code」は関数の定義に書かれてる感じになる。
bashでスクリプトをインクルードするときの同じく「. psスクリプト」で実行してあげたら、現在のコンテキストで実行してくれるので関数のインクルードがされる。 psスクリプト」で実行してあげたら現在のコンテキストで実行してくれるので関数のインクルードがされる。

## PowerShellの気持ち

### bashと比較

bashの場合はパイプを通して各コマンドに文字列が渡されて、各コマンドが改行で区切って1つのレコードと処理してる感じ。
PowerShellの場合は、コマンドや関数がパイプというキューからデータ一個取り出して、処理したデータを後続のパイプ(キュー)に出している感じ。
一つの長大な文字列をパースしながら処理単位を切り出しているのがbashだけど、PowerShellの場合シェル側で各データを分けて考えられてるのは大きな違い。

ただ、どちらも各コマンド・コマンドレットは、1つの単位でデータを処理して後続に渡しているイメージは共通だと思う。

### Write-Outputと省略

Write-Outputコマンドレットは後続のパイプに出力する関数。
また、上の「コツ」に書いた通り「変数」だけ書かれた行は「Write-Output 変数」となり、パイプに出力をしていることになる。
この書き方のおかげでPowerShellの関数(function、filter)は、「引数をもらって値を一つ返す」という通常の言語の「関数」ではなくて、
パイプからデータ取り出して後ろのパイプにデータを垂れ流していく存在と考えるほうが近い気がする。
PowerShellにおいて「return」は処理を止める程度の意味合いしかない。

### Out-Nullコマンドレット

「Out-Null」はbashでいう/dev/nullへのリダイレクトのようなイメージ、出力したオブジェクトはその流れから消滅する。

### %とforeach

```
%{Get-WindowRect $_.Name}
```
で書かれている$_はコマンドレットが受け取ったオブジェクト1個を表す変数。
まとめて扱う訳じゃなくて一個一個に対して処理をしている。

#### 行き場のないオブジェクト

パイプから入って次のパイプに出していると考えると、最後のコマンドから出力されるオブジェクトは行き場がなくなる。
行き場がないオブジェクトはToStringメソッドを実行してコンソールに出力される。

## 仕様

### function

PowerShellの関数は3つの処理ブロックを持つ。各オブジェクトが渡される前後に一度だけ実行されるBegin、Endブロックと各オブジェクトに対して実行されるProcessブロック。
filterはProcessブロックだけからなるfunctionになります。