PowerShellでps1ファイルに使う文字コードと改行コードについて

`PowerShell`といえば下記の2種類が存在しています。

- `Windows`+`.NET Framework`を背景とした`Windows PowerShell`
- `cross platform`+`.NET`を背景とした`PowerShell`

このように`WindowsPowerShell`と`PowerShell`が混在する環境があった場合に利用する`PowerShellスクリプトファイル`の文字コードと改行コードについて考えてみます。

理想としては、一度書いたスクリプトは手直しせずに他の環境でも実行できると最高ですが。
現状は文字コードと改行コードがネックになり、これはなかなか難しいかと思います。

## ドキュメント

[適切なエンコードの選択
](https://docs.microsoft.com/ja-jp/powershell/scripting/dev-cross-plat/vscode/understanding-file-encoding?view=powershell-7.1#choosing-the-right-encoding)

本記事を書くに当たって、調べていたら、MSDocsの`PowerShellドキュメント`の上記ページにエンコードについての記載がありました。

なんとなく感覚で理解してた部分についてまとめられていました。
下記引用。

> 主に Windows アプリケーションと Windows PowerShell を使用している場合は、BOM ありの UTF-8 または UTF-16 のようなエンコードをお勧めします。

> 複数のプラットフォームにまたがって作業する場合は、BOM ありの UTF-8 をお勧めします。

> 主に Linux 関連のコンテキストで作業する場合は、BOM なしの UTF-8 をお勧めします。

> Windows-1252 とラテン-1 は基本的にレガシ エンコードであり、できれば避けてください。 ただし、一部の古い Windows アプリケーションではそれらに依存している可能性があります。

> スクリプトの署名はエンコードに依存している点にも注意してください。つまり、署名されたスクリプトのエンコードを変更するには再署名が必要です。

改行コードについての記載はありませんが概ね下記のような理解で問題ないかと思います。

- OSは`Windows`を利用して`Windows PowerShell`を利用する場合　`UTF8+BOM + CRLF`。
- OSは`Windows`と`Linux`のクロスプラットフォームで`WindowsPowerShell`と`PowerShell`が混在する場合 `UTF8+BOM + CRLF`
- OSは`Linux`だけで`PowerShell`のみ利用 `UTF-8+BOMless + LF`

## 各種文字コードのスクリプトがそれぞれのプラットフォームでどのように動作するか確認してみる

- Windows 10 + WindowsPowerShell 5.1 で WindowsPowerShellプロンプトから実行
- Windows 10 + PowrShell 7.1.5 でPowerShellプロンプトから実行
- WSL(Ubuntu 20.04) + PowerShell 7.1.5　でBash（shebang）から実行
- WSL(Ubuntu 20.04) + PowerShell 7.1.5　でPowerShellプロンプトから実行

の組み合わせでそれぞれどうなるか確認してみます。

用意するスクリプトの組み合わせは下記

- UTF8+BOM + CRLF
- UTF8+BOM + LF
- UTF8+BOMLess + CRLF
- UTF8+BOMLess + LF


```PowerShell:UTF8-BOM-CRLF.ps1
#!/usr/bin/env pwsh

PROCESS {

    Set-StrictMode -Version Latest
    $ErrorActionPreference = "stop"

    Write-host "HelloWorld こんにちは世界
    on UFT8+BOM CRLF"

}
```

```PowerShell:UTF8-BOM-LF.ps1
#!/usr/bin/env pwsh

PROCESS {

    Set-StrictMode -Version Latest
    $ErrorActionPreference = "stop"

    Write-host "HelloWorld こんにちは世界
    on UFT8+BOM LF"

}
```

```PowerShell:UTF8-BOMLess-CRLF.ps1
#!/usr/bin/env pwsh

PROCESS {

    Set-StrictMode -Version Latest
    $ErrorActionPreference = "stop"

    Write-host "HelloWorld こんにちは世界
    on UFT8+BOMLess CRLF"

}
```

```PowerShell:UTF8-BOMLess-LF.ps1
#!/usr/bin/env pwsh

PROCESS {

    Set-StrictMode -Version Latest
    $ErrorActionPreference = "stop"

    Write-host "HelloWorld こんにちは世界
    on UFT8+BOMLess LF"

}
```

### Windows 10 + WindowsPowerShell 5.1 で WindowsPowerShellプロンプトから実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/124cbdac-4273-238a-fb24-524a03c04ef1.png)

UTF8-BOM付きのファイルは問題ありませんが、BOMLessの方は日本語が文字化けしているがわかります。

### Windows 10 + PowrShell 7.1.5 でPowerShellプロンプトから実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/c9271f0f-8ff8-d36e-3aef-cb1c497e499b.png)

Windows+PowerShellのケースだと今回用意したパターンでも問題なさそうです。

### WSL(Ubuntu 20.04) + PowerShell 7.1.5　でBash（shebang）から実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/14ede6f8-fe9a-4cc7-6a9e-f3bc9da25f15.png)

Bashからshabengを利用してPowerShellスクリプトを実行しようとすると、UTF8-BOMLess-LFのみ実行できました。

BOM付きのスクリプトについては、shabengの前にBOMが入っていることによっておかしくなり、CRLFの改行コードでもおかしい事になりと影響大です。

### WSL(Ubuntu 20.04) + PowerShell 7.1.5　でPowerShellから実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/9799b1c9-954e-dc70-da5e-9c164ce6f093.png)

PowerShellから実行するとすべていい感じに実行してくれています。

## まとめ

`Linux`環境で`shabeng`を利用して`PowerShell`スクリプトを実行しなくてはならない場合は、`UTF8+BOMLess LF`しか選択肢が無い事がわかりました。

それ以外のケースでは、だいたい`UTF8+BOM CRLF` or `UTF8+BOM LF`の利用が無難な感じがします。