業務でいきなりPowerShell開発する事になった人用メモ

# 初めに
吾輩はJavaエンジニアもどきである。スキルはまだない。
PowerShellとは無縁の生活をしていて、もちろん.Netとも関わりのないエンジニア。
突然沸いたPowerShellの仕事だったが、案件受けたものは仕方ないし覚えた事を備忘録程度に書いていこうと思う。
PowerShellのPの字も知らない人だったので、拡張子が `.ps1` ってことも初耳だった。
色々間違った知識を流出する可能性もあるので、存分に指摘してほしい。
無理せずに、ちょくちょく覚えた物から書き足していこうと思う。

# if編
## 比較演算子の使い方
HAHAHA、 `==` とか `<` とかそのまま使えないってマジかよ。エラー出たぞ。
絶対わからなくなるから、表にして書いとく。これ見ればif文（単独比較）はバッチリだぜ。

|PowerShellの表現|一般的な記号|意味|語源|
|:-:|:-:|:-:|:-:|
|-eq|==|等しい|equal|
|-ne|!=|等しくない|not equal|
|-gt|>|より大きい|greater than|
|-ge|>=|以上|greater or equal|
|-lt|<|より小さい|less than|
|-le|<=|以下|less or equal|

他に `-like` 、 `-notlike` 、 `-match` 、 `notmatch` 、なんていうのや他にも色々あるらしい。
ifでこんなん書いたら可読性落ちそうだし、余程のことじゃないと使わないだろうから省略する。
需要があれば記述しようと思う。

## 論理演算子の使い方
|PowerShellの表現|一般的な記号|意味|
|:-:|:-:|:-:|
|-and|&&|かつ|
|-or|&#124;&#124;|または|
|-not|!|以外|

実は `-not` に限っては記号の `!` を使用しても実はOKだったりする。

# for編
## 普通のforの使い方
あまり賢くはないが、まずは触りとして基本のforを書くとする。

```powershell
for ($index = 0; $index -lt 10; $index++) {
    #10回繰り返す
}
```

## 拡張forの使い方
Powershellには2つの拡張forが存在する。
具体的にはForEach-Objectとforeachだ。
ざっくりとした言い方をすると、繰り返し処理をするか、一度にまとめて処理をするか、だ。
並列で動いてOK、ある程度の高負荷でも耐えられるなら、まとめて処理をするforeachを使うと良いだろう。

```powershell
foreach ($user in $users) {
    #usersのデータが一気に処理される
    echo $user.name
}

$users | ForEach-Object -Process {
    #usersのデータが一件ずつ処理される
    echo $_.name
}
```

# 関数編

## functionの使い方

```PowerShell
function writeLog ($logText) {
    Write-Host($logText)
}
writeLog 'コンソールに表示されるログ'
```

おいおい、PowerShellってfunction使えたのかよ。
コマンドプロンプトと似たもんだと思ってたから関数使えないって思いこんでて、最初にコード長々書いてたよ。
でも、<font color="FireBrick">関数を呼び出すタイミングよりも先に必ずfunction書く必要ある</font>のな。
Javaのprivateの関数感覚で下にまとめて書いたら怒られた。

# 定数・変数編

## 変数を定義する

```PowerShell
$maxMoney=100
$snack='白いブラックサンダー'
```

おいおい、どっちも入るのかよ。勘弁してくれ。何が何だかわからなくなりそうだ。
調べてみると型もちゃんと定義できるようで安心した。Javaエンジニアとしては以下の形で書きたいものだ。

```PowerShell
[int]$maxMoney=100
[string]$snack='白いブラックサンダー'
```

## スコープの種類

関数に呼び込みはできるけど、結果が反映されないとか動きあるから注意が必要だ。
グローバル変数を使うんじゃないよ、みたいな考え方もあるとは思うのだが、テクニックとして覚えておくのは重要だろう。

|記述|機能|
|:-:|:-:|
|global|全体|
|script|定義したスクリプト|
|local|定義したスコープとその子スコープ|
|private|定義したスコープ|

# 設計編

## importはいずこへ？

importなんてないぞ。お陰で最初システム作る時は共通機能逐一書いていた。。。
だけど、<font color="FireBrick">共通機能逐一書く必要はない</font>。
外部ファイルを読み込み、そのfunctionを使えばいいだけのこと。
具体的な構文は以下の通りだ。

```Parent.ps1
function talkAnime([string]$title) {
  if($title -eq "kemono-friends") {
    echo "すごーい！"
  }
}
```

```Child.ps1
# 同階層にあるファイルとして仮定。この部分がimport文の意図に近い。
".\Parent.ps1"

# 関数名 引数のルール
talkAnime "kemono-friends"
```

## try-catchをしてエラーを探ろう

よくあるリスクを踏まえての記述をPowerShellでもやりましょうっていう話。
$_の記述が個人的に違和感があって、全然頭に入ってこないからサンプルとして残しておく。

```ApiSafe.ps1
try {
  Invoke-RestMethod -Uri $uri -Method Post -Headers $header -Body $body -ContentType "application/json"
} catch {
  Write-Error($_.Exception)
}
```

## CLASS使えるじゃん

先日列挙されまくっていたユーザー情報の変数をオブジェクトクラスに突っ込む事に成功した。
このように使うのだ。
まずはオブジェクトの方。

```User.ps1
class User {
  # 構成要素
  [string]$name;
  [string]$mail;

  # コンストラクタ
  User($datas) {
    $this.name = $datas.name;
    $this.mail= $datas.mail;
  }
}
```

次に引っこ抜き方。

```Log.ps1
.\User.ps1

# $datasは引数。APIの戻り値とかまとまってるデータをそのまま渡すのが効率良いと思う。
$user= New-Object "User" -ArgumentList $datas

# Qiitaの表示が若干変だけど、オブジェクトの要素取り出すのに$()で括って、$オブジェクト.要素で取り出せる。
Write-Host("ユーザーの名前は $($user.name) です。");
```

# 終わり
コメントや要望次第で追記したいと思いますが、転職を契機にPowerShellから離れましたゆえ、本記事の更新を終了します。