[powershellの学習を開始した日]
2018/11/8


[path パスを表示する]

$env:PATH -split ';'
（注）PATHは大文字でなければだめ

[dir ls Get-ChileItem]
dir
ls
Get-ChildItem
gci

上記4コマンドのいずれかでもdirを表示できる
なお、powershellでは大文字、小文字の区別はしない

詳細なプロパティを表示させる場合
Get-ChildItem | Select-Object *

メンバーを表示するには
Get-ChildItem | Get-Member


[コマンドレット（Cmdlet）Get-Command]
[link]T:\USB_DATA\Data1\技術資料\Powershell\ps-command.txt
コマンドレットとは、要は、PowerShellで利用可能なコマンドのことである。
標準で129種類にも及ぶコマンドレットが提供されており、これらコマンドレットを組み合わせることで、従来、コマンド・プロンプトやWSHでは実現できなかった（もしくは困難であった）処理を限りなく短いコードで実現することができる。

利用可能なコマンドレットの一覧を取得するのはGet-Commandコマンドレットの役割だ。Get-Commandコマンドレットを利用することで、名前（Name）、構文（Definition）などを確認することができる

代表的な動詞
Add	追加する
Clear	すべて削除する
ConvertXxxxx	変換する
Copy	複製する
Export	エクスポートする
Format	整形する
Get	取得する
Import	インポートする
Move	移動する
New	新規に作成する
Remove	削除する
Set	設定する
Start	開始する
Stop	停止する
Write	書き込み／表示する

代表的な名詞
Alias	エイリアス
Content	文字列
History	コマンド履歴
Item（ChildItem）	項目（フォルダ／ファイル、レジストリ項目など）
Location	作業場所（カレントフォルダなど）
Object	オブジェクト
Path	パス
Process	プロセス
Service	サービス


[コマンドレッド Get-Help ヘルプ機能 タブ補完機能 tab補完機能]
使用例
Get-Help Get-ChildItem
-fullオプションを付与することで更に入力の種類や戻り値の型、メモなど、ヘルプとして用意されたすべての情報を、それぞれ出力することも可能だ

例
Get-Help Get-ChildItem -full

PowerShellには入力途中のコマンド名を補完する「タブ補完機能」が用意されている。
タブ補完機能を利用するには、コマンドの入力中に［Tab］キーを押下すればよい。すると、入力された文字列が合致するコマンドが、［Tab］キーを押すたびに順次表示されるので、正しい候補が表示された時点で［Enter］キーや空白キーなどを押すと、確定させることができる。
例えば「g」「e」「t」「-」と4文字入力してから［Tab］キーを押すと、そのたびに「Get-Acl」「Get-Alias」「Get-AuthenticodeSignature」……などと表示されるので、適切なものが表示された時点で、［Enter］キーや空白キーなどを押せばよい。


[powershell 日本語モード　英語モード　切り替え]
PowerShellを英語モードにする
chcp 437

Powershellを日本語モードにする
chcp 932

これらはWindowsでのみ有効である


[エイリアス alias エリアス 新規登録方法]
エイリアスは必要に応じて自分で登録することも可能だ。例えば、Remove-Itemコマンドレット（指定された項目を削除）のエイリアスとして「remove」を設定するならば、以下のように記述すればよい*。
Set-Alias remove Remove-Item

現在のセッション上で行ったエイリアスの定義は、その場限りのものであり、PowerShellを起動する都度に行う必要がある。
このような毎回利用するエイリアスの定義は、プロファイル上で行うのが好ましい。


[powershellの戻り値]
PowerShellのコマンドレットは、戻り値として「.NET Frameworkのオブジェクト（以降「.NETオブジェクト」と呼ぶ）」を返す。

※コマンドレットの戻り値型を確認するコード
PS > $result = Get-Date
PS > $result.GetType()

IsPublic IsSerial Name      BaseType
-------- -------- ----      --------
True     True     DateTime  System.ValueType


[変数]
PowerShellの変数は、1文字目は「$」、2文字目以降は「英字、数字、アンダースコア」とする必要がある
変数「$_」はPowerShell上で利用可能な特殊変数の1つで、パイプ経由で渡されたオブジェクトを表す


[Where-Objectコマンドレット　パイプ処理　条件式　スクリプト・ブロック]
Where-Objectコマンドレットにおいて、条件式はスクリプト・ブロック（{ ～ }で囲まれた部分）に記述することができる。

例１
※サイズが1Mbytes以上のファイルのみを表示
PS > Get-ChildItem | Where-Object {$_.Length -ge 1MB}
「-ge」は比較演算子の1つで、「以上」を表す
変数「$_」はPowerShell上で利用可能な特殊変数の1つで、パイプ経由で渡されたオブジェクトを表す

例２
※最終更新日が6カ月以上前のファイルのみを取得する例 
PS > Get-ChildItem | Where-Object {$_.LastWriteTime -lt (Get-Date).AddMonths(-6)}
AddMonthsメソッドは、Get-Dateコマンドレットによって返されるDateTimeオブジェクトのメソッドで、指定された月数を現在の日付に加算するものだ。
従って、ここではGet-ChildItemコマンドレットから渡されたFileInfoオブジェクト群のLastWriteTimeプロパティ（最終更新日）を6カ月前の日付と比較し、それ以前のもののみを出力することになる。

例３
 Get-Service | Where-Object { $_.Status -eq "Stopping" }
＊サービスが停止しているものだけ抽出する
（注）Get-ServiceはWindowsのみで動作する

[比較演算子]
演算子	概要	例（条件式の部分のみ）
-eq	等しい（＝）	$_.Name -eq "wga.log"
-ne	等しくない（≠）	$_.Name -ne "wga.log"
-gt	より大きい（＞）	$_.Length -gt 1MB
-ge	以上（≧）	$_.Length -ge 1MB
-lt	未満（＜）	$_.Length -lt 1MB
-le	以下（≦）	$_.Length -le 1MB
-like	あいまい検索（ワイルドカード）	$_.Name -like "*.log"
-notlike  ワイルドカードによる比較
-match	正規表現検索	$_.Name -match "[a-z]{1,}\.log"
-notmatch  正規表現による比較
-contains 　　左側のコレクションに右側の値が含まれている 3,4,5 -contains 4 $true
-notcontains　左側のコレクションに右側の値が含まれていない 3,4,5 -contains 4 $true

文字列の比較はデフォルトで大文字小文字を区別しない．
文字列比較で大文字／小文字を区別する場合には「c」、しない場合には「i」を演算子の先頭に付ける。例えば「-ieq」などとする。


[ForEach-Objectコマンド]
ForEach-Objectコマンドレットは、パイプ経由で渡された入力オブジェクトを順番に出力する。
例えば、次のリストはGet-ChildItem／Where-Objectコマンドレット経由で取得した「6カ月以上更新のないファイル」を削除するためのコマンドの例である。

※6カ月以上更新のないファイルを削除する 
PS > Get-ChildItem |
>> Where-Object {$_.LastWriteTime -lt (Get-Date).AddMonths(-6)} |
>> ForEach-Object {$_.Delete()}

行末を「|」（パイプ記号）で終えた場合、PowerShellではコマンドが複数行にまたがるものと見なし、次行では「>>」という続きの入力を促すプロンプト記号が表示される。
パイプ処理を伴うコマンドは、往々にして長く複雑になりがちであるので、このように、適宜改行を入れておくと分かりやすいだろう。


[Format-Listコマンドレット]
Format-Listコマンドレットは、パイプ経由で渡されたオブジェクトの内容をリスト形式で出力する。
コマンドレットは、デフォルトで、その処理結果をテーブル形式で出力するが、表示すべきプロパティの数が多い場合には、テーブル形式では一部の情報が省略されてしまうなど、十分な情報が得られない。
そのような場合には、Format-Listコマンドレットでリスト形式に整形すれば、必要な情報を見やすい形式で出力できる。

次のリストは、Get-ChildItemコマンドレットで取得したファイル一覧を、Format-Listコマンドレットで整形した例だ。
※Get-ChildItemコマンドレットの処理結果をリスト形式に整形する 
PS > Get-ChildItem | Format-List *

PSPath            : Microsoft.PowerShell.Core\FileSystem::C:\Documents and Settings\Yamada\Favor
PSParentPath      : Microsoft.PowerShell.Core\FileSystem::C:\Documents and Settings\Yamada
PSChildName       : Favorites
PSDrive           : C
PSProvider        : Microsoft.PowerShell.Core\FileSystem
PSIsContainer     : True
Mode              : d-r--
Name              : Favorites
  ...中略...
LastWriteTime     : 2007/07/10 11:58:02
LastWriteTimeUtc  : 2007/07/10 2:58:02
Attributes        : ReadOnly, Directory

PSPath            : Microsoft.PowerShell.Core\FileSystem::C:\Documents and Settings\Yamada\My Do
PSParentPath      : Microsoft.PowerShell.Core\FileSystem::C:\Documents and Settings\Yamada
……（以下省略）…… 

＊）このコマンドを実行すると、カレント・フォルダの内容によっては大量の結果が表示されるはずだ。このような場合、通常は、先ほども紹介したmoreコマンドを利用して、「Get-ChildItem | Format-List * | more」のように1ページずつ表示させるとよい。

表形式では表示されていなかった多くのプロパティ情報が表示されていることが確認できるはずだ。Format-Listコマンドレットでパラメータとして「*」を指定しているのは、入力オブジェクトで公開されているすべてのプロパティを出力するという意味である。もしも特定のプロパティ――例えば、NameプロパティとLengthプロパティだけを出力したいという場合には、
PS > Get-ChildItem | Format-List Name,Length
のように、出力したいプロパティをカンマ区切りで指定することも可能だ。

［参考］PowerShell独自のプロパティ
　Format-Listコマンドレットによる出力結果を見て、はたと違和感を覚えた方もいるかもしれない。というのも、本来のDirectoryInfo／FileInfoオブジェクトには存在しないはずの「PS～」で始まるプロパティが多く表示されているのだ。
　これは、（名前からも容易に想像できるように）PowerShellが本来の.NETオブジェクトを拡張しているためだ。
Get-ChildItemコマンドレットに限らず、PowerShellでは多くのコマンドレットが戻り値オブジェクトを内部的に拡張し、必要な情報を追加している。
どのような拡張がなされているのか興味のある方は、それぞれのコマンドレットの結果をFormat-Listコマンドレットでリスト表示してみるとよいだろう。


[moreコマンドの実体]
PowerShellでも、「dir | more」というコマンド・プロンプトふうの記述は利用可能だ。
もっとも、このmoreコマンドは、厳密にはコマンド・プロンプトで提供されていたそれではなく、PowerShellの「関数」（エイリアスではない）を利用して擬似的にマッピングされているにすぎない。
具体的な実装については、以下のリストのようにすれば確認できる。

PS > Get-Command -CommandType function "more" | Format-List
Name        : more
CommandType : Function
Definition  :
              param([string[]]$paths)
              $OutputEncoding = [System.Console]::OutputEncoding
              if($paths) {
                  foreach ($file in $paths)
                  {
                      Get-Content $file | more.com
                  }
              } else { $input | more.com }
            

[ドライブ drive]
PowerShell関連のドキュメントやヘルプを読み進めていくと頻繁に登場するのが、この「ドライブ」というキーワードだ。ドライブとは、ファイル・システムにおけるドライブと同様、PowerShell上のコマンドレットからアクセス可能な「データの保管場所」のことである。ファイル・システムのドライブからフォルダやファイルにアクセスできるのと同様に、（例えば）レジストリドライブからはレジストリ項目に、環境変数ドライブからは環境変数に、それぞれアクセスできるというわけだ。

デフォルトで、どのようなドライブが公開されているのかを確認するには、Get-PSDriveコマンドレットを使用する。
※PowerShellで利用可能なドライブを一覧表示させる 

PS > Get-PSDrive

Name       Provider      Root
----       --------      ----
Alias      Alias
C          FileSystem    C:\
cert       Certificate   \
D          FileSystem    D:\
E          FileSystem    E:\
Env        Environment
Function   Function
HKCU       Registry      HKEY_CURRENT_USER
HKLM       Registry      HKEY_LOCAL_MACHINE
Variable   Variable
Z          FileSystem    Z:\

このように、おなじみのファイル・システムのドライブ（C:ドライブやD:ドライブ）のほかに、Alias:ドライブ（エイリアス）、HKCU:ドライブ（レジストリのHKEY_CURRENT_USER）、Env:ドライブ（環境変数）など、さまざまなドライブが用意されていることが確認できる。
これらドライブはユーザーが自前で追加することも可能だ。
従って、例えばPowerShell上からデータベースにアクセスするようなドライブを追加することも可能だ。
このための具体的なコードは以下のページでも紹介されている。難解ではあるが、興味のある方は一読をお勧めする。

https://blogs.msdn.microsoft.com/powershell/2007/06/20/demo-sql-provider-code/


[環境変数を一覧表示]
※定義済みの環境変数を一覧表示する 

PS C:\Documents and Settings\Yamada> Set-Location Env:
PS Env:\> Get-ChildItem

Name                   Value
----                   -----
Path                   C:\WINDOWS\system32;C:\WINDOWS;
C:\WINDOWS\system32\WBEM;C:\Program Files\Intel\DMIX;C...
TEMP                   C:\DOCUME~1\Yamada\LOCALS~1\Temp
SESSIONNAME            Console
PATHEXT                .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;
.WSF;.WSH;.PSC1
USERDOMAIN             DIMENSION5100C
PROCESSOR_ARCHITECTURE x86
SystemDrive            C:
TZ                     JST-9
……（以下省略）……

Set-Locationは、従来のコマンド・プロンプトにおけるcdコマンドに相当するコマンドレットだ。
つまり、ここではカレントのドライブを、デフォルトのCドライブからEnv（環境変数）ドライブに切り替えているというわけだ。
実際、ここではプロンプトの表示を省略せずに掲載しているが、もともとの「PS C:\Documents and Settings\Yamada >」から「PS Env:\>」に変更されていることが確認できるだろう。
あとは、Get-ChildItemコマンドを実行することで、カレント・ドライブ配下の情報として、ここでは環境変数名と対応する値の一覧を表示することができる。


[［コラム］ドライバの実体は「プロバイダ」　Get-PSDriveコマンドレット　Provider　プロバイダー]
PowerShellのドキュメントを眺めていると、ドライバと並んで、よく登場するのが「プロバイダ」というキーワードだ。
もっとも、またもや新しい概念かと身構える必要はない。
プロバイダとは、ドライバの実装だと思っていただければよいだろう。
ドライバの機能を実際に提供している.NET Frameworkベースのクラス・ライブラリが、プロバイダなのである。

先ほど、Get-PSDriveコマンドレット（リスト「※PowerShellで利用可能なドライブを一覧表示させる」参照）で、PowerShell標準で提供されているドライバを確認したが、その出力項目に「Provider」というプロパティが含まれているのに気付いた方もいたかもしれない。これがそれぞれのドライブに対応するプロバイダの名前となる。これを確認すると、例えばC:、D:、E:などのドライブはFileSystemプロバイダで、HKCU:、HKLM:などのドライブはRegistryプロバイダで提供されていることが確認できる。


[PowerShellスクリプトの基本 スクリプト・ファイルの実行方法 Set-ExecutionPolicyコマンドレット]
ファイルのベース名には任意の名前を指定できるが、PowerShellスクリプトの拡張子は「.ps1」としなければならない。

ただし拡張子を「.ps1」としたスクリプト・ファイルをエクスプローラなどからダブルクリックしてもPowerShellが自動起動するわけでは「ない」点には注意が必要である（試してみれば分かるように、「.ps1」ファイルはデフォルトでメモ帳によって開かれる）。

PowerShellではスクリプト・ファイルを実行する場合に必ず絶対パスか相対パス形式でファイルを指定しなければならない。
つまり上の例であれば、
PS > ./Begin.ps1
または、
PS > C:\Windows\Temp\Begin.ps1
（拡張子「.ps1」は省略しても構わない）

PowerShellではセキュリティ上の理由から、デフォルトでスクリプトの実行が無効に設定されている。
そのため、スクリプト・ファイルを実行するためには、あらかじめPowerShellのスクリプト実行ポリシーを変更しておく必要がある。
実行ポリシーを変更するにはSet-ExecutionPolicyコマンドレットを利用する。
PS > Set-ExecutionPolicy RemoteSigned

Set-ExecutionPolicyコマンドレットで指定可能な実行ポリシーには以下のようなものがある。
実行ポリシー	概要
Restricted	すべてのスクリプトを実行不可
AllSigned	すべてのスクリプトに証明書を要求
RemoteSigned	インターネット経由でダウンロードしたスクリプトのみ証明書を要求
Unrestricted	すべてのスクリプト実行を許可（ただしインターネット経由でダウンロードしたコードは実行確認のみあり）


[変数　命名規則]
PowerShellにおいては、（多くのスクリプティング言語と同様）あらかじめ変数を宣言する必要はない。PowerShellでは、初めて値が代入されたタイミングで、必要に応じて変数が生成される（*）。

* 従って、厳密にはPowerShellの変数には「未初期化」という状態はない。PowerShellでは「値を持つ変数」か「存在しない変数」があるだけである。

変数の命名規則
PowerShellでは変数名を以下の規則に従って命名する必要がある。
　・先頭文字は「$」で始まること
　・2文字目以降は任意の英数字、またはアンダースコア（_）であること
厳密には${～}のように、中カッコで変数名を囲めば任意の文字を利用できる。例えば以下のような変数名でもよい。
　　${Windows PowerShell + .NET Framework}
　　

[変数のデータ型]
PowerShellは、（やはり多くのスクリプティング言語と同様）データ型を区別しない言語である。ただし厳密にはデータ型を持たないわけではなく、与えられた実データに応じてPowerShellが自動的に適切なデータ型を与えてくれる。従って、次のようなコードもPowerShellでは正しい。
　$x = 123
　$x = "abc"


[Write-Output　指定された式の値を標準出力に出力する。　変数を表示]
例
PS > $x = "1"
PS > $y = 2
PS > $z = $x + $y
PS > Write-Output $z
12  ……文字列として変数$x、$yが連結処理される

PS > $x = 1
PS > $y = "2"
PS > $z = $x + $y
PS > Write-Output $z　（*）
3  ……整数として変数$x、$yが加算処理される


[明示的に変数の型を宣言する方法]
以下のリストのように変数名の先頭に角カッコで囲んだデータ型を明示する（*）。
PS > [System.Int32] $x = 10
PS > $x = 13.5
PS > Write-Output $x
14  ……強制的にInt32型にキャスト
PS > $x = "abc"
値 "abc" を型 "System.Int32" に変換できません。エラー: "入力文字列の形式が正しくありません。"
発生場所 行:1 文字:3
+ $x  <<<< = "abc"　　……Int32型にキャストできないためエラー

* これはPowerShellにおけるキャスト構文である。例えば、「$x = [System.Int32] 1.3」のようにすることで、右辺の値（1.3）をInt32型にキャストすることもできる。

PowerShellでは「データ型があいまいなままに使用することも、厳密にデータ型を区別して利用することも可能であること」「厳密にデータ型を指定した場合にもできるだけデータをその型に合致するように自動変換が行われること」を覚えておいていただきたい。


[変数の型名のエイリアス]
PowerShellでは.NET Frameworkで提供される型名をそのまま利用できるが、一部のよく利用するデータ型についてはエイリアス（別名）が用意されており、より短い型名で表記できる。以下に、PowerShellで利用可能な主な型エイリアスをまとめておく。

エイリアス	.NET Frameworkの型名エイリアス
byte	 System.Byte
int	System.Int32
long	 System.Int64
single、float	System.Single
double	System.Double
decimal	System.Decimal
char	 System.Char
bool	 System.Boolean
string	System.String
array	System.Array
xml	System.Xml.XmlDocument
type	 System.Type


[文字列の自動展開　シングルクォートで囲まれた文字列　ダブルクォートで囲まれた文字列]
PS > $name="山田"
PS > Write-Output "私の名前は $name です。"
私の名前は 山田 です。
PS > Write-Output '私の名前は $name です。'
私の名前は $name です。

このように、文字列に含まれる「$name」がシングルクォートで囲まれた場合にはそのまま出力されるのに対して、ダブルクォートで囲まれた場合には評価された結果（ここでは「山田」）として表示される。
このように、PowerShellではダブルクォートで囲まれた文字列では「変数展開」が行われるというわけだ。

エスケープ・シーケンスは、シングルクォートの中では認識されないので、要注意


[エスケープ・シーケンス　エスケープシーケンス escape sequence]
エスケープ・シーケンス	概要
`0　NULL
`a　alert
`b	  バックスペース
`f　form feed
`n	  改行
`r	  キャリッジ・リターン
`t	  タブ
`v　vertical quote

PS > Write-Output "私の名前は`n $name です。"
私の名前は
 山田 です。
PS > Write-Output '私の名前は`n $name です。'
私の名前は`n $name です。

[ヒア・ドキュメント here document ヒア・ドキュメントを利用した長い文字列の定義]
ヒア・ドキュメント（here document）とは、（通常は複数行にまたがる）大量のテキストをスクリプト・インラインで記述するための仕組みだ。
ヒア・ドキュメントは「@"＜改行＞～＜改行＞"@」（または「@'＜改行＞～＜改行＞'@」）の形式で記述できる。

PS > $body=@"
>> こんにちは、WINGSの山田です。
>> PowerShellの世界をご一緒に楽しみましょう。
>> "@
>>   ……ここで［Enter］キーのみを入力して終了する
PS > Write-Output $body

こんにちは、WINGSの山田です。
PowerShellの世界をご一緒に楽しみましょう。

ヒアドキュメントを利用しないで長い文字列を定義（2）
PS > $body="こんにちは、`'WINGS`'の山田です。
>> `"PowerShell`"の世界をご一緒に楽しみましょう。"
>>
PS > Write-Output $body
こんにちは、'WINGS'の山田です。
"PowerShell"の世界をご一緒に楽しみましょう。
このように、文字列にシングルクォート／ダブルクォートを含み、かつ、ヒア・ドキュメントを利用しない場合にはクォートをエスケープする必要がある。
もちろん、これは大量のテキストをインラインで記述する場合には、エスケープ漏れの原因にもなるし、そもそもエスケープが必要な個所を確認すること自体が煩雑な作業だ。
そこでヒア・ドキュメントの登場というわけである。ヒア・ドキュメントは（繰り返しであるが）「@"＜改行＞～＜改行＞"@」（または「@'＜改行＞～＜改行＞'@」）を文字列の区切りとしているので、文字列中にクォートを自由に含めることができる。
後々に文字列を変更した場合に、思わぬ不具合の原因とならないよう、複数行に及ぶ長いテキストを表す場合には（クォートの有無にかかわらず）ヒア・ドキュメントを利用することをお勧めしたい。


[配列と連想配列（ハッシュテーブル）]
PS > $x = 1,2,3
PS > Write-Output $x[0]
1  ……0番目の要素を出力
PS > $z = @{FirstName="Yoshihiro"; LastName="Yamada"; Birth="Shizuoka"}
PS > Write-Output $z["FirstName"]
Yoshihiro  ……FirstName要素を出力
PS > Write-Output $z.FirstName
Yoshihiro  ……FirstName要素を出力

配列／連想配列を生成する一般的な構文は、以下のとおりだ。
　要素, 要素, 要素, ...　……配列
　@{キー名=値; キー名=値; ...}　……連想配列
ただし配列はカンマ演算子（,）で生成するほか、以下のように記述することもできる。
　@(要素, 要素, 要素, ...)
空の配列を明示的に宣言するには、単に「()」とするのではなく、「@()」のように記述する（空の連想配列を生成する場合は「@{}」）。

宣言された配列／連想配列にアクセスするには、
　$変数名[インデックス番号]
　$変数名["キー名"]
のように角カッコ表記でインデックス番号やキー名を指定すればよい。ただし連想配列についてはドット演算子を利用して、
　$変数名.キー名
の形式で取得することも可能である（プロパティ表記）。
キー名が静的に決まる場合には角カッコ表記／プロパティ表記いずれを利用しても構わないが、キー名を変数として渡したいなど動的に変更する必要がある場合には、角カッコ表記を使用する必要がある。


[スクリプト 条件分岐やループ 制御構文 条件分岐 if ～ elseif ～ else]
if ～ elseif ～ else
$x = 1
if($x -eq 1){
  Write-Output '変数$xは1です。'
}else{
  Write-Output '変数$xは1ではありません。'
}
ブロック内の命令が1文しかない場合にも、PowerShellではスクリプト・ブロックを表す中カッコ（{ ～ }）を省略することはできない。

$x = 100
if($x -ge 80){
  Write-Output '変数$xは80以上です。'
}elseif($x -ge 40){
  Write-Output '変数$xは40以上80未満です。'
}else{
  Write-Output '変数$xは40未満です。'
}


[スクリプト 条件分岐やループ 制御構文 条件分 switch ～ case]
$x = 1
switch($x){
  1 {Write-Output '変数$xは1です。'}
  2 {Write-Output '変数$xは2です。'}
  3 {Write-Output '変数$xは3です。'}
  default {Write-Output '変数$xは1、2、3ではありません。'}
}

$x = 1
switch($x){
  1 {Write-Output '変数$xは1です。'}
  1 {Write-Output '変数$xは1です。（2）'}
  3 {Write-Output '変数$xは3です。'}
  default {Write-Output '変数$xは1、2、3ではありません。'}
}
この例では確かに、
変数$xは1です。
変数$xは1です。（2）
のような結果が返されることが確認できる。

もしもif命令同様、最初に合致したブロックのみを実行したければ、ブロックの末尾にbreak命令を記述すればよい。
$x = 1
switch($x){
  1 {
      Write-Output '変数$xは1です。'
      break
    }
  1 {
      Write-Output '変数$xは1です。（2）'
      break
    }
  3 {
      Write-Output '変数$xは3です。'
      break
    }
  default {Write-Output '変数$xは1、2、3ではありません。'}
}

［コラム］switch命令のオプション
本文で紹介した内容は、ほかのスクリプティング言語でもほぼ共通の内容であるが、PowerShellのswitch命令ではこれに加えて、やや面白い機能が提供されている。
switch命令の後方にオプションを指定すれば、式評価にワイルドカードや正規表現が利用できるのだ。次の例ではワイルドカードを使用している。
$x = "XYZ"
switch -wildcard ($x){
  "X*"  {Write-Output '変数$xは"X"で始まります。'}
  "X_"  {Write-Output '変数$xは"X"＋1文字です。'}
  "XA*" {Write-Output '変数$xは"XA"で始まります。'}
}
結果は
変数$xは"X"で始まります。
「-wildcard」オプションは、式の内容をワイルドカードで評価することを表す。
そのほか、値の大文字／小文字を区別しない「-case」オプション、式の内容を正規表現パターンとして評価する「-regex」オプションなども利用できる


[スクリプト 条件分岐やループ 制御構　ループ構文（1） ――for命令とforeach命令――]
配列内の数値をすべて合計するためのコード（for命令を利用した場合）
$ary=@(100,120,300)
for($i=0; $i -lt 3; $i++){
  $sum += $ary[$i];
}
Write-Output $sum
このコードを実行すると、配列内に含まれる数値（100、120、300）の合計である520が得られる。

for命令ではループの回数を、
　for(初期化式; 終了条件; 増分式)
の形式で指定する。「初期化式」はループの始まりで評価される式で、ここではカウンタ変数（ループの回数を管理するための変数）である$iを0で初期化している。

もっとも、このように配列やコレクションの内容を順番に処理するようなケースでは、foreach命令を利用した方がより直感的にコードを記述できる。以下は先ほどのコードをforeach命令で書き換えたものだ。
配列内の数値をすべて合計するためのコード（foreach命令を利用した場合）
$ary=@(100,120,300)
foreach($dat in $ary){
  $sum += $dat;
}
Write-Output $sum

foreach命令では、
　foreach(一時変数 in 配列、コレクション){
のように指定することで、配列から順に要素を取り出し、読み出す要素がなくなるまでループを繰り返す。
取り出された要素は一時変数に格納され、スクリプト・ブロック内で参照できる。

このように、foreach命令はごく直感的に利用できる制御構文の1つであるが、ここで1つ疑問に思われる方もいるかもしれない。というのも、PowerShellにはコマンドレットとしてよく似た機能を持つForEach-Objectが提供されている。これを利用すれば、foreach命令と同様の処理を行うことが可能である。
例えば先ほどの例はForEach-Objectを利用して、次のように書き換えることができる。
@(100,120,300) | ForEach-Object {$sum += $_}
Write-Output $sum
多くの場合、この2つはプログラマの好みによって使い分けて構わないが、内部的な挙動としては微妙な違いもあるので要注意だ。
というのも、foreach命令が入力元となる要素（オブジェクト）をすべて取得してからループ処理を行うのに対して、ForEach-Objectコマンドレットはオブジェクトを1つずつ読み込みながら処理する。
このため、前者の方が処理に際してより多くのメモリを必要とすることになる。
一方、一括してオブジェクトを取得するため、処理の内容によっては前者の方が高速に動作する可能性がある。
要は、消費リソースとパフォーマンスとをてんびんにかけて、両者を使い分ける必要があるということだ。


[スクリプト 条件分岐やループ 制御構　ループ構文（2） ――while／do ～ while命令――]
while／do ～ while命令は、いずれも与えられた条件式が真と評価される間だけループを繰り返す。
※while命令を利用した例
$i=0;
$sum=0;
$ary=@(100,120,300)
while($i -lt 3){　　……変数$iが3未満の場合の間、ループを継続
  $sum += $ary[$i];
  $i++;
}
Write-Output $sum

※do ～ while命令を利用した例
$i=0;
$sum=0;
$ary=@(100,120,300)
do{
  $sum += $ary[$i];
  $i++;
}while($i -lt 3)　　……変数$iが3未満の場合の間、ループを継続
Write-Output $sum

コードを実行すると、どちらも配列要素の合計値である520が得られる。
条件式の記述がスクリプト・ブロックの前方／後方いずれにあるかという点を除いては非常によく似た両者であるが、1点だけ大きく異なる点があるので、要注意だ。

というのも、while命令は条件式をブロックの前方で判定（前置判断）するのに対して、do ～ while命令は条件式をブロックの後方で判定（後置判断）するのである。
つまり、do ～ while命令では条件の真偽にかかわらず、「最低1回は必ず」ループが実行されるということである。
一方、while命令ではループの開始時点で条件式が偽と評価される場合にはループは「1度も実行されない」。


[Powershellのバージョンを調べる version]
$PSVersionTable


[コマンドモードでアプリケーション／ファイルを実行する start-process]
start-process アプリ名　オプション
または
start-process  http://www.yahoo.co.jp
または
start-process T:\USB_DATA\Documents\手帳備忘録.doc
または
start-process chrome microsoft.com


[powershell入門 webページの連載記事一覧]
[Link]https://codezine.jp/article/corner/10


[Windowsのポチポチ業務を爆速化するPowerShell]
[Link]https://tonari-it.com/windows-powershell-start/
このWEBページには、以下のリンクがある

Windowsのポチポチ業務を爆速化するPowerShell、はじめのハードルぐーーんと下げてみます！
Windowsのポチポチ業務を爆速化するPowerShell、キーボードを使わずササっと起動する方法
Windowsのポチポチ操作を爆速化するPowerShellの絶対条件！ディレクトリとその移動をマスターしよう！
Windowsのポチポチ業務を爆速化するPowerShell、コマンドレットを腹の底から理解する！
Windowsのポチポチ業務を爆速化するPowerShell、オンラインヘルプでコマンドレットを使い倒す！
Windowsのポチポチ業務を爆速化するPowerShell、統合開発環境ISEを紹介します！
Windowsのポチポチ業務を爆速化するPowerShell、スクリプトを実行するための準備
Windowsのポチポチ業務を爆速化するPowerShell、フォルダを作るスクリプトの作り方
Windowsのポチポチ業務を爆速化するPowerShell、if文を使いフォルダの有無で処理を分岐させる方法


[コンソールに文字列を表示するにはWrite-Hostというコマンドレットを使います。]
Write-Host ‘Hello World!’

Write-Host のaliasは echo
例
Write-Host ‘Hello World!’


[ファイルの読み込み ファイルの中身を画面に表示する]
Get-Content FileName


[ubuntu 18.04にpowershellをインストールする install]
https://github.com/PowerShell/PowerShell
からダウンロードして .deb ファイルをクリックするとインストールパッケージが
起動してインストールしてくれる。

[LinuxMINT 19.3に powershell preview 7.1 をインストールする]
https://github.com/PowerShell/PowerShell
からダウンロードして .deb ファイルをクリックするとインストールパッケージが
起動してインストールしてくれる。

手動でインストールする場合
sudo dpkg -i powershell-preview_7.1.0-preview.1-1.ubuntu.18.04_amd64.deb
sudo apt-get install -f


[コンソールの基本操作　ショートカットキー shortcut key]
←→　：カーソル（入力位置）を左右に移動
Ctrl+"+" 、 Ctrl+"-"：カーソルを単語単位で移動
Ctrl + END ：カーソル位置より後の文字を削除
Ctrl + HOME ：カーソル位置より前の文字を削除
Ctrl + SPACE ：入力候補一覧の表示
ENTER：入力したコマンドを実行
TAB ：コマンド保管を行う（「get-C まで打ってTABキーを押すと、「Get-Children」に保管する。
BackSpace ：カーソル位置の直前の文字を削除
DELETE ：カーソル位置の文字を削除
INSERT ：挿入／上書きモードの切り替え
Tab + C ：現在の入力や実行をキャンセルして新規の行に進む

マウスの操作
ドラッグ　：テキストを選択します
ダブルクリック　：その位置にある単語を選択
テキスト選択中に右ボタン　：クリップボードにコピー
左ボタン + 選択範囲を選んでマウス右ボタン　：クリップボードにコピー
右ボタン　：カーソル位置に現在のクリップボードの内容をペースト


[大量の空ファイルを作成する ファイルの新規作成]
1..10 |  ForEach-Object {New-Item -Path item$_.txt}

実行結果は

    Directory: T:\usb_data\ptemp

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2018/12/17     20:22              0 item1.txt
-a----       2018/12/17     20:22              0 item2.txt
-a----       2018/12/17     20:22              0 item3.txt
-a----       2018/12/17     20:22              0 item4.txt
-a----       2018/12/17     20:22              0 item5.txt
-a----       2018/12/17     20:22              0 item6.txt
-a----       2018/12/17     20:22              0 item7.txt
-a----       2018/12/17     20:22              0 item8.txt
-a----       2018/12/17     20:22              0 item9.txt
-a----       2018/12/17     20:22              0 item10.txt


[ファイルやフォルダを削除する Remove-Item del]
Remove-Item [パス] [オプション]

Remove-Itemコマンドレットの主なオプション
-Path ファイルのパスを指定する。省略可能
-Exclude 指定したパターンに一致するファイルやフォルダを指定する
-Force 隠しファイルや読み取り専用ファイルなどを削除する
-Recurse 指定したフォルダとそのサブフォルダに含まれるファイル／フォルダを削除する


[ファイル／フォルダを作成する]
New-Item [ディレクトリパス] [オプション]

New-Itemコマンドレットの主なオプション
-Path　ディレクトリパスを指定する。省略可能
-ItemType　作成する種類を指定する。省略時はファイル作成となる
-Force　既存のファイルがあっても上書きする
-Value　指定した文字列をデータに含める

ファイルの作成例
New-Item C:\Work\Test1.txt

フォルダの作成例
New-Item C:\Work\Sub -ItemType Directory

「abc」という文字列を含んだファイルを作成する
New-Item C:\Work\Test2.txt -Value abc


[ファイルの名前を変える　名称変更 Rename-Item rni ren]
Rename-Item OldFileName NewFileName

10個のファイルをリネームする
元のファイル
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2018/12/18    15:06              0 item1.txt
-a----        2018/12/18    15:06              0 item10.txt
-a----        2018/12/18    15:06              0 item2.txt
-a----        2018/12/18    15:06              0 item3.txt
-a----        2018/12/18    15:06              0 item4.txt
-a----        2018/12/18    15:06              0 item5.txt
-a----        2018/12/18    15:06              0 item6.txt
-a----        2018/12/18    15:06              0 item7.txt
-a----        2018/12/18    15:06              0 item8.txt
-a----        2018/12/18    15:06              0 item9.txt

リネームコマンドレット
Get-ChildItem item*.txt -File | Rename-Item -NewName {$_.Name.Replace("item","file")}
実行結果
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2018/12/18    15:06              0 file1.txt
-a----        2018/12/18    15:06              0 file10.txt
-a----        2018/12/18    15:06              0 file2.txt
-a----        2018/12/18    15:06              0 file3.txt
-a----        2018/12/18    15:06              0 file4.txt
-a----        2018/12/18    15:06              0 file5.txt
-a----        2018/12/18    15:06              0 file6.txt
-a----        2018/12/18    15:06              0 file7.txt
-a----        2018/12/18    15:06              0 file8.txt
-a----        2018/12/18    15:06              0 file9.txt


[$_とは　自動変数]
$_とは、現在パイプラインに渡っているオブジェクトを表す自動変数である。


[csvファイルへの出力 Export-Csv]
get-childitem | Select-Object name, directoryname,length

Name       DirectoryName                     Length
----       -------------                     ------
file.txt   /mnt/datadisk/USB_DATA/powershell      0
file1.txt  /mnt/datadisk/USB_DATA/powershell      0
file10.txt /mnt/datadisk/USB_DATA/powershell      0
file2.txt  /mnt/datadisk/USB_DATA/powershell      0
file3.txt  /mnt/datadisk/USB_DATA/powershell      0
file4.txt  /mnt/datadisk/USB_DATA/powershell      0
file5.txt  /mnt/datadisk/USB_DATA/powershell      0
file6.txt  /mnt/datadisk/USB_DATA/powershell      0
file7.txt  /mnt/datadisk/USB_DATA/powershell      0
file8.txt  /mnt/datadisk/USB_DATA/powershell      0
file9.txt  /mnt/datadisk/USB_DATA/powershell      0

上記の結果をCSVに変換する
Get-ChildItem -Path file* | Select-Object Name,DirectoryName,Length | Export-Csv -Path output.csv
output.csvの中身は以下の通り
"Name","DirectoryName","Length"
"file.txt","/mnt/datadisk/USB_DATA/powershell","0"
"file1.txt","/mnt/datadisk/USB_DATA/powershell","0"
"file10.txt","/mnt/datadisk/USB_DATA/powershell","0"
"file2.txt","/mnt/datadisk/USB_DATA/powershell","0"
"file3.txt","/mnt/datadisk/USB_DATA/powershell","0"
"file4.txt","/mnt/datadisk/USB_DATA/powershell","0"
"file5.txt","/mnt/datadisk/USB_DATA/powershell","0"
"file6.txt","/mnt/datadisk/USB_DATA/powershell","0"
"file7.txt","/mnt/datadisk/USB_DATA/powershell","0"
"file8.txt","/mnt/datadisk/USB_DATA/powershell","0"
"file9.txt","/mnt/datadisk/USB_DATA/powershell","0"


[ファイルの中身を表示する Get-Content]
NAME
    Get-Content
    
SYNTAX
    Get-Content [-Path] <string[]> [-ReadCount <long>] [-TotalCount <long>] [-Tail <i
    nt>] [-Filter <string>] [-Include <string[]>] [-Exclude <string[]>] [-Force] [-Cr
    edential <pscredential>] [-Delimiter <string>] [-Wait] [-Raw] [-Encoding <Encodin
    g>] [-AsByteStream] [<CommonParameters>]
    
    Get-Content -LiteralPath <string[]> [-ReadCount <long>] [-TotalCount <long>] [-Ta
    il <int>] [-Filter <string>] [-Include <string[]>] [-Exclude <string[]>] [-Force]
     [-Credential <pscredential>] [-Delimiter <string>] [-Wait] [-Raw] [-Encoding <En
    coding>] [-AsByteStream] [<CommonParameters>]
    
ALIASES
    gc
    type


[csvファイルを読み込みオブジェクトに変換する Import-Csv]
集計する場合
Import-Csv output.csv | Measure-Object

合計するには
Import-Csv output.csv | Measure-Object -Sum -Property Length


[Webサイトが正常に動作しているのかを確認する web site ステータスコード status code]
Webサイトが正常に動作しているのかを確認する web site

(Invoke-WebRequest -Uri https://google.com).StatusCode
実行結果の戻り値は
200
この200は正常応答を示す


[Visual Studio Code VS Code のインストール　テキストエディタ]
Mintの場合
　　ソフトウエアで「Visual Studio Code」を検索するとヒットするのでインストールできるが、
　　下記方法の方が良い
　　　sudo dpkg -i code_1.30.1-1545156774_amd64.deb
　　　sudo apt-get install -f
　　ここで、debファイルは https://code.visualstudio.com/download から
　　ダウンロードしたものである

直接ダウンロードする場合（Windows, MINT共）
　　https://code.visualstudio.com/download
　　からダウンロードできる

日本語化
　　左端の縦メニューバーの一番下の四角いアイコン Extensions をクリック
　　左上のExtensions の入力欄に Japanese と入力し日本語化
　　Japanese Language Pack をインストールする
　　VSCodeを再起動する

Powershell拡張のインストール
　　「表示」−「拡張機能」をクリック
　　「Maeketplaceで拡張機能を検索する」と薄く表示されている検索欄に「poserashell」と記入
　　「powershell」が表示されるので、インストールする
　　「powershell Pro Tool」もインストールする

特定バージョンのPowerShellを使用する
　　「表示」−「コマンドパレット」を開く
　　「PowerShell Show Session Menu」と入力
　　表示される一覧から「Switch to PowerShell Core ...」を選択
あるいは、MINTの場合
　　「ファイル」ー「基本設定」ー「設定」の順に開く
　　一番上の setting の行の{}の間に
　　"powershell.powershellExePath":"/opt/microsoft/powershell/6/pwsh" を追加する
　　
　　
[fedora（reh hat）にpowershellをインストールする]
curl https://packages.microsoft.com/config/rhel/7/prod.repo | sudo tee /etc/yum.repos.d/microsoft.repo
sudo yum install -y powershell
pwsh


[powershell 6.2をVS Code で表示する]
１．PowerShell拡張（PowerShell Pro Tools）をインストールする
２．［表示］→［コマンドパレット］の順に開く、あるいは、Ctrl + Shift + P
３．「PowerShell Show Session Menu」と入力
４．表示される一覧から「Switch to PowerShell Core 6.2(x64)」を選択
５．powershell.powerShellExecPathエントリが設定される


[コメントの書き方 comment]
shellでもコマンドラインでも # のあとはコメントとなり、実行されない
#これは実行されない
get-childitem #これはコマンドだけ実行される

複数行のコメント
<#  これはコメントです #>

[VS Codeでのデバッグ debug]
デバッグしたい行をハイライト（選択）し、 F8 を押すと、その行だけの実行結果をコマンドライン上に表示してくれる


[ブレークポイントを使ったデバッグ break point debug]
ブレークポイントとはその行で実行を詰めるという意味である

VS Code でブレークポイントを設定したい行にカーソルを合わせ、 F9 を押すとその行にブレークポイントが設定される。
もう1度 F9 を押すと解除される（トグルスイッチとなっている）。
ブレークポイントを設定したら F5 を押すと、スクリプトが実行され、ブレークポイントで動作がとまる。

次のブレークポイントに進む場合は、さらに F5 を押す。
デバッグを中断する場合は Shift + F5 を押す。


[if文]
条件は丸カッコ ( ) にboolean型を使用し、実行することを波カッコ { } に書く。

ifの構文例
if (条件）{
    # 条件が満たされるときに実行すること
}
elseif (次の条件) {
    # 条件が満たされるときに実行すること
}
else {
    # どの条件にも該当しなかったときに実行すること
}


[代表的なコマンドレット]
Get-Location　　Pathを表示する
Set-Location　　cdと同じ、Directoryに移動する
Get-Date　　日付と時間を表示する
Get-ChildItem　　dirと同じ
Get-ChildItem -Recurse　　下部ディレクトリも示す
Write-Output "コンソールに文字を表示する"　　コンソールに表示する場合
Write-Host "コンソールに文字を表示する"　　コンソールに表示する場合
Clear-Host　　コンソールに表示されている内容を消去する
Copy-Item -Path .\テストフォルダー1\サブフォルダー1\サンプルファイル1.txt -Destination .\テストフォルダー2\サブフォルダー1
　　テストフォルダー1 のサブフォルダー1 内にある、サンプルファイル1.txt をテストフォルダー2 のサブフォルダー1 内にコピーする
Copy-Item -Path .\テストフォルダー1\サブフォルダー2\* -Destination .\テストフォルダー2\サブフォルダー2\ -Recurse
　　テストフォルダー1 のサブフォルダー2 内にある、全てのファイルをテストフォルダー2 のサブフォルダー2 内にコピーする
Move-Item -Path .\テストフォルダー1\サブフォルダー1\サンプルファイル1.txt -Destination .\テストフォルダー2\サブフォルダー1
　　テストフォルダー1 のサブフォルダー1 内にある、サンプルファイル1.txt をテストフォルダー2 のサブフォルダー1 内に移動する
Rename-Item -Path .\テストフォルダー1\サブフォルダー2\ -NewName 新サブフォルダー1
　　テストフォルダー1 のサブフォルダー2 を別のフォルダ名に変更する
Remove-Item -Path .\テストフォルダー2\サブフォルダー1\サンプルファイル1.txt
　　テストフォルダー2 のサブフォルダー1 内にある、サンプルファイル1 を削除する
Remove-Item -Path .\テストフォルダー2\サブフォルダー2 -Recurse　　ファイルすべてを削除する
Get-History　　コマンドの履歴を示す
Clear-History　　コマンドの履歴をクリア


[ファイルの有無を調べる Test-Path Get-Content]
if (Test-Path "C:\temp\script\users.txt") {
 
    Write-Output "ファイルがあります。"
 
} else {
 
    Write-Output "ファイルはありません。"
 
}
 
if (Test-Path "C:\temp\scripts\users.txt") {
 
    Get-Content "C:\temp\scripts\users.txt"
 
} else {
 
    Write-Output "ファイルはありません。"
 
}


[csvファイルを読み込む]
Import-Csv t:\USB_DATA\access\銀行.csv -Encoding SJIS

（注）-Encoding SJIS を指定しないとSift JIS文字は文字化けする


[オブジェクト Object]
簡単にいうと、オブジェクトとはクラスという設計図を基にして、それを実体化（インスタンス化）したものである。例を挙げると、前回プロセスの一覧を取得するGet-Processというコマンドレットを紹介したが、このコマンドレットによって得られるのは.NET Frameworkに含まれるProcessクラスのオブジェクト（インスタンスともいう）である。


[csvファイルの読み込み]
import-csv eventmemo.csv -encoding SJIS | Format-List

import-csv test.csv -encoding SJIS | where-object{$_.曜 -eq "火"} | format-list


[論理演算子]
論理演算子は与えられた引数を評価し，1つの出力（TrueまたはFalse）を返します．

演算子　　説明 
-and　　　論理積 
-or 　　　 論理和 
-not　　　論理否定 
-! 　　　 論理否定 

$false は1以外の値
$true = 1

[代入演算子]
代入演算子は，値を代入するための演算子です．

演算子　　説明 
= 　　　　指定した値を変数に設定します
+=　　　　指定した値を変数の値に加算するか，指定した値を既存の値に追加します
-=　　　　指定した値を変数の値から減算します
*=　　　　指定した値で変数の値を乗算するか，指定した値を既存の値に追加します
/=　　　　指定した値で変数の値を除算します
%=　　　　指定した値で変数の値を除算し，余りを変数に代入します


[算術演算子]
算術演算子は四則演算を表す演算子です．

演算子　　説明 
+ 　　　　2つの値を加算する 
- 　　　　一方の値から他方の値を減算する 
- 　　　　値を負の数値に変換する 
* 　　　　2つの値を乗算する 
/ 　　　　2つの値で除算を行う 
% 　　　　除算で発生した余りを返す 

また，演算子には次の優先順位があります．演算の順番を変更するには，優先したい演算を「かっこ ()」で括ります．

1.　　　　- (負の数を表すマイナス記号)
2.　　　　*，/，%
3.　　　　+，- (減算を表すマイナス記号)


[csvファイルの配列への読み込み]
$warituke = import-csv ./suitou2.csv -encoding SJIS
write-host $warituke                                                     
@{ID=1; 割付名称=さがみや; 内容=さがみや; 費目=家計費; 備考=} @{ID=2; 割付名称=オータニ; 内容=オータニ; 費目=家計費; 備考=} @{ID=3; 割付名称=ヨークベニマル; 内容=ヨークベニマル; 費目=家計費; 備考=} @{ID=4; 割付名称=ウエルシア; 内容=ウエルシア; 費目=家計費; 備考=} @{ID=5; 割付名称=ツルハドラッグ; 内 容=ツルハドラッグ; 費目=家計費; 備考=} @{ID=6; 割付名称=割付No.6; 内容=; 費目=; 備考=}

write-host $warituke[3].割付名称                                         

$himoku=import-csv t:\usb_data\powershell\suitou4.csv -encoding SJIS
$himoku.length
38

$himoku[37]
結果は
ID 費目
-- --
38 Biglobe


[Helpファイルの更新　update-help]
月に1度くらいこのアップデートを実行するのが望ましい
powershell を管理者権限で実行すること


[ファイルの中身をページごとに表示する Get-Content、Out-Host]
ファイルの中身をページごとに表示する 
Get-Content、Out-Host
Get-Content ファイルパス | Out-Host -Paging


[多次元配列に要素を追加する]
処理対象ファイル
file1.txt
a1
a2
a3
a4

file2.txt
b1
b2
b3
b4

目標とする結果
console
a1,b1
a2,b2
a3,b3
a4,b4

sample.ps1
# 変数宣言
[string[][]]$columns = @()
[string[]]$column = @()

# file1.txtの内容を$columnに要素を追加して代入
$column += "a1"
$column += "a2"
$column += "a3"
$column += "a4"

# $columnを配列として$columnsを代入
$columns += ,@($column)

# $columnを空にする
[string[]]$column = @()

$column += "b1"
$column += "b2"
$column += "b3"
$column += "b4"

# 再度$columnを配列として$columnsを代入
$columns += ,@($column)

# 以降ファイル数分を繰り返す。

Write-Host ($columns[0][0] + "," + $columns[1][0])
Write-Host ($columns[0][1] + "," + $columns[1][1])
Write-Host ($columns[0][2] + "," + $columns[1][2])
Write-Host ($columns[0][3] + "," + $columns[1][3])

出力結果
console
a1,b1
a2,b2
a3,b3
a4,b4

ポイント
point
$columns += ,@($column)


[配列の型宣言 型の表示]
[int[]]$array=@()

型の表示
$array.gettype().fullname


[変数の型を調べる]
$a の型を調べるには
write-host $a.gettype().fullname
とする


[不要になった変数$aを削除する]
remove-variable a
（注）変数名の$は記入しない


[suiteu4.csv を読み込んで、費目を配列$aに代入する]
$b = import-csv t:\usb_data\access\suitou4.csv -encoding SJIS
[string[]]$a = @()
$b | foreach-object{$a = $b.'費目'}
$a

結果は
ASAHIネット
NHK
NTT電話
ガス
ガソリン
その他
その他家電保守
その他自動車関係
家屋・設備の保守費
家計費
火災保険
介護関係
介護保険料
携帯電話
固定資産税
交際費
交通傷害保険
国民健康保険税
国民年金保険料
自治会費・常会費
自動車税
自動車保険
住宅金融公庫
小遣い
床屋
浄化槽保守点検
新聞
水道
知昭の国民年金基金
地方税
電気
灯油
病院・薬
普門寺関係
ソフトバンク
安子の葬式
安子の法事
Biglobe


[コンソール出力の整形　フォーマット　数値にカンマを付ける]
PowerShellの処理結果出力はいろいろありますが、個人的に一番使いであると思う整形です。

C/C++だと、printfでフォーマット出力しますが、こいつをPowerShellでやるとどんな感じになるかってお話です。

PowerShellにもフォーマットを指定する文字があるので、まずはそいつから。

フォーマット指定文字
#	1桁の数値(余分な0は表示されない)
0	1桁の数値(0表示される)
.(ピリオド)	小数点位置の指定
,(カンマ)	カンマ編集の指定
x	小文字16進(x4とすると4桁を指定)
X	大文字16進(X4とすると4桁を指定)

フォーマット表現
フォーマット文字列を使ってフォーマット表現はこんな感じにします。

数値をカンマ付にする

#,0
数値を固定長にしてリーディングゼロをつける

000000
小数以下の指定桁表示

0.000
4桁の小文字16進数

x4
4桁の大文字16進数

X4

数値のフォーマット(ToStringメソッドを使う)
では、具体的にフォーマット文字列を使って出力のフォーマットをします。まずは単純な数値のフォーマットです。

数値をカンマ付にする

PS C:\> $Num = 12345.6789
PS C:\> $Num.ToString("#,0")
12,346
数値を固定長にしてリーディングゼロをつける

PS C:\> $Num = 12345.6789
PS C:\> $Num.ToString("00000000")
00012346
小数以下の指定桁表示

PS C:\> $Num = 12345.6789
PS C:\> $Num.ToString("0.00")
12345.68
4桁の小文字16進数

PS C:\> $Num= 255
PS C:\> $Num.ToString("x4")
00ff
4桁の大文字16進数

PS C:\> $Num= 255
PS C:\> $Num.ToString("X4")
00FF
 
複数項目の整形
「-f」を使う
C/C++のprintfっぽい使い方ができるのが「-f」です。1つの値は「{n}」で表現し、nが変数の順番になります。

項目の表示幅は「{n,s}」のようにsで表現します。nだけだと右揃え、-sにすると左揃えになります。

数値のフォーマットは「{n,s:Format}」で表現します。

PS C:\> $Str = "ABCD"
PS C:\> $Num = 12345.678
PS C:\> "Sring:{0,-8} Number:{1,12:#,0.00}" -f $Str, $Num
Sring:ABCD     Number:   12,345.68
 
「[String]::Format」を使う
ちょっと変わったところでは、Stringのスタティック メンバーを使って「[String]::Format」でも整形できます。表記はこっちの方がpritfに近いかも?

$Str = "ABCD"
$Num = 12345.678
[String]::Format("Sring:{0,-8} Number:{1,12:#,0.00}", $Str, $Num)
Sring:ABCD     Number:   12,345.68


[文字列操作]
配列に変数をセットして結合
SyntaxHighlighterについて

# 配列に3変数を格納
$a = "aaaaa", "bbbbb", "ccccc"
 
# -区切りで3変数を結合
$ret = [string]::Join("-", $a)
 
# 画面表示
$ret

+を使用して結合
$ret = "aaaaa" + "bbbbb" + "ccccc"
# 表示
$ret

+= 演算子による連結
$ret = "aaaaa"
$ret += "bbbbb"
$ret += "ccccc"
# 表示
$ret

*= 演算子による連結
$ret = "hoge"
# $ret変数の中身を5回結合
$ret *= 5
# 表示
$ret

先頭からある文字数分取得したい場合
substring関数を使用する。

・構文
substring(開始位置,取得文字数)

先頭から5文字取得するサンプル
$ret = "1234567890".substring(0,5)
# 表示
$ret

後方からある文字数分取得したい場合
開始位置を-と設定。
$val = "1234567890"
$ret = $val.substring($val.Length -5,5)
# 表示
$ret


[文字列操作メニュー]
[Link]https://hiros-dot.net/PowerShell/stringMenu.htm


[文字を右寄せ/左寄せするには　成形]
文字列を右寄せするには、PadLeftメソッド、左寄せするにはPadRightメソッドを使用します。
引数で指定した文字数になるまでスペースを追加します。スペースではなく指定した文字で埋めたい場合は第2引数にその文字を指定します。

sample1の(1)は文字列"ABC"を右寄せし、空白を含めて6文字になるようにしています。
sample1の(2)は文字列"ABC"を左寄せし、空白を含めて6文字になるようにしています。
((2)は右側に３文字の空白が追加されたことが確かめられるよう - を末尾に追加しています）

sample1
PS C:\Users\HIRO> $a = "ABC"            ---(1)
PS C:\Users\HIRO> $a.PadLeft(6)
   ABC
PS C:\Users\HIRO> $a = "ABC"            ---(2)
PS C:\Users\HIRO> $a.PadRight(6) + "-"
ABC   -

sample2の(1)は文字列"ABC"を右寄せし、Xを含めて6文字になるようにしています。
sample2の(2)は文字列"ABC"を左寄せし、Xを含めて6文字になるようにしています。

sample2
PS C:\Users\HIRO> $a = "ABC"          ---(1)
PS C:\Users\HIRO> $a.PadLeft(6,"X")
XXXABC
PS C:\Users\HIRO> $a = "ABC"          ---(2)
PS C:\Users\HIRO> $a.PadRight(6,"X")
ABCXXX


[基礎文法最速マスター]
[Link]http://winscript.jp/powershell/202


[関数宣言の基本　サブルーチン　subroutine]
# 関数宣言の基本
function Get-Test {
    return "test"
}
# 注：returnを付けなくても関数内で出力された値はすべて呼び出し元に返却される。返却したくない場合は出力値をを[void]にキャストするか|Out-Nullに渡す。
 
# 引数を指定する場合
function Get-Test {
    param($param1,$param2)
    return $param1 + $param2
}
関数宣言の基本　サブルーチン　subroutine  

# 引数を指定する場合の簡易的な記述法
function Get-Test($param1,$param2) {
    return $param1 + $param2
} 
 
# 引数の型を指定する場合
function Get-Test {
    param([string]$param1,[string]$param2)
    return $param1 + $param2
} 
 
# 関数の呼び出し方(,区切りではなくスペース区切りであることに注意)
Get-Test "引数1" "引数2"
 
# 引数の順序はパラメータ名（引数名）を指定すると自由に指定可能
Get-Test -param2 "引数2" -param1 "引数1"
 
# フィルタ宣言の基本
filter Get-Odd {
    if($_ % 2 -eq 1){
        return $_
    }else{
        return
    }
} 
 
# フィルタの使用
@(1..10) | Get-Odd


[変数名に変数を含める]
（例１）
$LIST = import-csv FILE.csv
$hash_table = @{}
foreach ( $line in $LIST ){
   $num = $line.address
   $hash_table.Add("$num","$line")
}

（例２）
For ( $i = 1 ; $i -lt 10 ; $i++)
{
    # testで始まる連番の変数を作成する
    Set-Variable -Name ("test0" + $i) -Value ($i)
}
# Nameプロパティで変数名を指定し、Valueプロパティで変数内の値を指定します。

# 作成したtestが付く変数を全て取得する
Get-Variable -Name test*


[OSの種類を調べる]
$a = [Environment]::OSVersion
$os = $a.Platform

Write-Host $os では
Windowsの場合
Win32NT

Linuxの場合
Unix

を返す


[OSによりデータの格納フォルダを変更する場合の例]
$dmy = [Environment]::OSVersion
$os = $dmy.Platform
if($os -eq "Win32NT"){
    $s1="t:\USB_DATA\access\suitou1.csv"  #  ID, 年月日, 内容, 費目, 金額, 備考
    $s4="t:\USB_DATA\access\suitou4.csv"  #  ID, 費目
}
elseif($os -eq "Unix"){
    $aa = get-childitem env:XDG_DATA_DIRS
    if($aa.value.contains("cinnamon")){
        $s1 = "/mnt/datadisk/USB_DATA/Access/suitou1.csv"
        $s4 = "/mnt/datadisk/USB_DATA/Access/suitou4.csv"
    }
    else{
        $s1 = "/mnt/t/USB_DATA/Access/suitou1.csv"
        $s4 = "/mnt/t/USB_DATA/Access/suitou4.csv"
    }
    
}
else{
    write-host "動いているOSはWindowsでもLinuxでもありません。"
    break
}


[ユーザー定義オブジェクトを作成する]
# 配列
$arr = @()

# ユーザー定義オブジェクトを追加
$p = @{index=-1; name=""; age=-1}
$arr += New-Object PSObject -Property $p
$arr += New-Object PSObject -Property $p
$arr += New-Object PSObject -Property $p

$arr[0].index = 0
$arr[0].name  = "あいうえお"
$arr[0].age   = 30

$arr[1].index = 1
$arr[1].name  = "かきくけこ"
$arr[1].age   = 18

$arr[2].index = 2
$arr[2].name  = "さしすせそ"
$arr[2].age   = 99


# こっちの方がいいかも
# ただし、index が inde とかになっていてもエラーにはならない
<#
$arr += New-Object PSObject -Property @{index=0; name="あいうえお"; age=30}
$arr += New-Object PSObject -Property @{index=1; name="かきくけこ"; age=18}
$arr += New-Object PSObject -Property @{index=2; name="さしすせそ"; age=99}
#>

# 表示
$arr
name          age      index
----          ---      ----
あいうえお     30       0
かきくけこ     18       1
さしすせそ     99       2

Windows PowerShell 3.0以上であれば、
$c = [pscustomobject]@{index=1; name="あいうえお"; age=30}
のようにも記述できるらしい。


[ファイルまたはディレクトリの存在を確認する file dir test-path]
Test-Path 絶対ファイル名/絶対パス名

存在すれば True を返し、存在しなければ False を返す


[ファイルに出力する Out-File]
Out-File 

SYNTAX
    Out-File [-FilePath] <string> [[-Encoding] <Encoding>] [-Append] [-Force] [-NoClobber] [-Width <int>] [-NoNewline] [-InputObject <psobject>] [-WhatIf] [-Con
    firm] [<CommonParameters>]

    Out-File [[-Encoding] <Encoding>] -LiteralPath <string> [-Append] [-Force] [-NoClobber] [-Width <int>] [-NoNewline] [-InputObject <psobject>] [-WhatIf] [-Co
    nfirm] [<CommonParameters>]
    
    
[数値を右詰でコンソールに出力する]
$n = 23
([String]$n).Padleft(10)
$n
        23

となる
23の前にスペースが8個入っている

[文字列のバイト数をカウントする Encoding.GetByteCount]
文字列のバイト数をカウントするには、Encoding.GetByteCount メソッドを使用します。
sample1では文字列 "あいうえお" のバイト数を取得しています。

sample1
PS C:\Work> [System.Text.Encoding]::GetEncoding("Shift_Jis").GetByteCount("あいうえお")
10


[バイナリファイルの読み書き]
Get-ContentコマンドレットのEncodingパラメータに「Byte」を指定するとバイナリーでの読み込みができる

[読み込み]
[Byte[]]$bFile = Get-Content "F:\Desktop\NorthwindJ.mdf" -Encoding Byte

[書き込み]
Set-Content "F:\Desktop\NorthwindJ2.mdf" -Value $bFile -Encoding Byte


[テキストファイルをバイト単位で切り出す]
ファイル名： get_SubstringByByte.ps1

function Get-SubStringBytes($f_text, $f_start, $f_Len) {
    $enc = [System.Text.Encoding]::Default
    $bytes = $enc.GetBytes($f_text)
    return $enc.GetString($bytes, $f_start, $f_Len)
}
 
function main_proc()
{
    if ($script:args.length -ne 1) {
        Write-Host "第１引数に入力ファイル名を指定してください。"
        return -1
    }
 
    $input = $script:args[0]
     
    $i = 0
    Get-Content $input | foreach {
        $i++
        Write-Host ([string]$i + "行目: " + $_)
        Write-Host (" --> 1～4バイトを抽出: " + (Get-SubStringBytes $_ 0 4))
        Write-Host (" --> 3～8バイトを抽出: " + (Get-SubStringBytes $_ 2 6))
    }
     
    return 0
 
}
 
# 処理開始
$ret = main_proc
 
if ($ret -eq 0) {
    exit 0
} else {
    exit 1
}


[ファイルを読み込みこんで、１６進数でバイナリ表示する]
$file = "C:\work\test.txt"
 
[Byte[]]$data = Get-Content $file -Encoding Byte
 
$buf = ''
$cnt = 0
 
Write-Host
 
foreach($a in $data)
{
    $buf = $buf + ' ' + $a.ToString("X2")     
    $cnt += 1
    if ($cnt -eq 16)
    {
        Write-Host $buf
        $buf = ''
        $cnt = 0 
    }
}
 
Write-Host $buf


[バイナリファイルをダンプ Format-Hexコマンドレッド]
PS C:\temp> Format-Hex -Path ".\pngfile.dat"

           パス: C:\temp\pngfile.dat

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52  ?PNG........IHDR
00000010   00 00 01 8C 00 00 00 E6 08 02 00 00 00 49 43 25  ...?...a.....IC%
... (以下略)

ファイルが小さければ、このまま問題なく使えるが、ファイルが大きい場合に出力をmoreに食わせるとメモリ消費や実行時間が増え、表示し始めるまでに時間がかかってしまう現象があった。
ページャを使わなければそのようなことはないが、出力が大量に出てしまう。ctrl-cで止められるが、使いにくい。
試した結果、moreを使うよりSelect-Objectのほうが表示し始めるまでの時間が速いことがわかった。
どうやらmoreは前段の処理結果をすべて一旦メモリに蓄えてから表示しはじめるようで、Select-Objectならばすぐにパイプライン処理が始まる点が違う模様。

Select-Objectを使う

# 先頭256バイトを表示(16バイト単位のByteCollectionのため16で割る)
PS C:\temp> Format-Hex .\bitmap100KB.dat | Select-Object -First (256/16)

           パス: C:\temp\bitmap100KB.dat

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00000000   42 4D C6 90 01 00 00 00 00 00 36 00 00 00 28 00  BMÆ......6...(.
00000010   00 00 91 02 00 00 34 00 00 00 01 00 18 00 00 00  .....4.........
... (以下略)

# 8KBスキップして256バイトを表示
PS C:\temp> Format-Hex .\bitmap100MB.dat | Select-Object -Skip (8KB/16) -First (256/16)

           Path: C:\temp\bitmap100MB.dat

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00002000   0A 2D 4E 0A 2D 4E 0A 2D 4E 0A 2D 4E 0A 2D 4F 0A  .-N.-N.-N.-N.-O.
00002010   2D 4F 0A 2D 4F 0A 2C 4F 09 2C 4F 09 2C 4F 09 2C  -O.-O.,O.,O.,O.,
... (以下略)


# アドレス0x1C00から256バイト表示
PS C:\temp> Format-Hex .\bitmap1MB.dat | Select-Object -Skip (0x1C00/16) -First (256/16)

           パス: C:\temp\bitmap1MB.dat

           00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

00001C00   4C 08 28 4C 07 28 4C 06 28 4D 06 28 4D 06 28 4C  L.(L.(L.(M.(M.(L
00001C10   06 29 4D 07 2A 4E 08 2B 4E 09 2A 4E 08 29 4E 07  .)M.*N.+N.*N.)N.
... (以下略)

ただしSelect-Objectを使っても、skipがMB単位とか大きくなるほど、やはり時間がかかってしまいどうしようもなかった。基本的にファイル先頭付近を見るのに使うしかなさそう。Format-Hexにskipオプションができればいいのだが。


[ファイルを1行ずつ読み取る]
foreach($line in Get-Content .\file.txt) {
    if($line -match $regex){
        # Work here
    }
}


[変数の一覧を表示する、予約変数]
    Get-Childitem variable:


[pause的な関数、画面上で一時ホールドする]
Read-Host "続けるにはENTERキーを押して下さい" 


[配列がnullかを確認する方法]
# 値をセットしないと NULL になる。
$a;
 
# 左辺に $null を持ってくる。
if($null -eq $a)
{
    Write-Host '変数は NULL です。'; # こっちにくる。
}
else
{
    Write-Host '変数は NULL ではありません。';
}
 
# NULL を格納した配列を作成
$b = @($null, $null);
 
if($null -eq $b)
{
    Write-Host '変数は NULL です。';
}
else
{
    Write-Host '変数は NULL ではありません。'; # こっちにくる。
} 

実行結果は次の通りです。

変数は NULL です。
変数は NULL ではありません。 


[変数が NULL かを確認する方法]
サンプルコードは次の通りです。

PowerShell（実行可能なサンプルコード）

# 値をセットしないと NULL になる。
$a;
 
if($a -eq $null)
{
    Write-Host '変数は NULL です。';
}
else
{
    Write-Host '変数は NULL ではありません。';
} 
上記の実行結果は次の通りです。

変数は NULL です。 


[コンソールの表示色 color について]
例
Write-Host '████████' -ForegroundColor DarkYellow

指定できる色
値	メンバー名
0	Black
1	DarkBlue
2	DarkGreen
3	DarkCyan
4	DarkRed
5	DarkMagenta
6	DarkYellow
7	Gray
8	DarkGray
9	Blue
10	Green
11	Cyan
12	Red
13	Magenta
14	Yellow
15	White


[ソースコードの式の途中で改行する方法]
PowerShell のソースコード上で、 1 つの式が長くなる場合などに式の途中で改行するには
文末にバッククォート ( ` ) を記述します。使い方は VB や VBA で式の改行に使用する
アンダースコア ( _ ) と同じです。

# ` を文末につけることで式の途中で改行できます
$ans = 21987765334 `
     / 1024 `
     / 1024 `
     / 1024
 
Write-Host $ans
 
# 改行して引数を記述することもできます
New-Item "c:\temp\myfile.txt" `
    -type file `
    -value "test"
 
 
# 改行してパイプでつなぐこともできます
Get-Process `
   | Where-Object {$_.CPU -gt 500} `
   | Select-Object -first 3
 
# ちなみにパイプを後ろに置く場合は ` 無しで改行できます
Get-Process | 
   Where-Object {$_.CPU -gt 500} |
   Select-Object -first 3


[Powershellの正規表現
「^」：行頭
「$」：行末
「*」：直前文字の0回以上の繰り返し
「+」：直前文字の1回以上の繰り返し
「?」：直前文字の0回か1回の繰り返し
「{n}」：直前の文字のn回の繰り返し
「{n,}」：直前の文字のn回以上の繰り返し
「{n,m}」：直前の文字のn回からm回までの繰り返し
「.」：改行を除く任意の文字
「|」：または（例：x|yはxかyにマッチ）
「[ ]」：[ ]で囲まれた文字のどれかにマッチ（例：[xyz」はxかyかzの文字にマッチ）
「^」：[^]で囲まれた文字以外の文字にマッチ（例：[^xyz」はx、y、z以外の文字にマッチ）
「( )」：サブパターン
「\d」：数字
「\D」：\d以外
「\s」：空白、改行、タブなどの空白文字
「\S」：\s以外
「\w」：英数字および、アンダーバー
「\W」：\w以外の文字
「\b」：単語境界
「\B」：非単語境界
「\」：\nや\t等のエスケープシーケンス
「[a-z]」：aからzまでのアルファベット
「[A-Z]」：AからZまでのアルファベット
「[0-9]」：0から9までの数字


[文字コード表]
文字コードの指定は、下の表を参考にしてください。 

コード
ページ値    WebNameプロパティ   EncodingNameプロパティ
---------------------------------------------------------------
0           shift_jis           日本語 (シフト JIS)
37          IBM037              IBM EBCDIC (米国 - カナダ)
437         IBM437              OEM 米国
500         IBM500              IBM EBCDIC (インターナショナル)
737         ibm737              ギリシャ語 (DOS)
775         ibm775              バルト言語 (DOS)
850         ibm850              西ヨーロッパ語 (DOS)
852         ibm852              中央ヨーロッパ言語 (DOS)
855         IBM855              OEM キリル語
857         ibm857              トルコ語 (DOS)
860         IBM860              ポルトガル語 (DOS)
861         ibm861              アイスランド語 (DOS)
863         IBM863              フランス語 (カナダ)(DOS)
865         IBM865              ノルウェー語 (DOS)
866         cp866               キリル語 (DOS)
869         ibm869              ギリシャ語 モダン (DOS)
874         windows-874         タイ語 (Windows)
875         cp875               IBM EBCDIC (ギリシャ語 モダン)
932         shift_jis           日本語 (シフト JIS)
936         gb2312              簡体字中国語 (GB2312)
949         ks_c_5601-1987      韓国語
950         big5                繁体字中国語 (Big5)
1026        IBM1026             IBM EBCDIC (トルコ語 Latin-5)
1200        utf-16              Unicode
1201        unicodeFFFE         Unicode (Big-Endian)
1250        windows-1250        中央ヨーロッパ言語 (Windows)
1251        windows-1251        キリル語 (Windows)
1252        Windows-1252        西ヨーロッパ言語 (Windows)
1253        windows-1253        ギリシャ語 (Windows)
1254        windows-1254        トルコ語 (Windows)
1255        windows-1255        ヘブライ語 (Windows)
1256        windows-1256        アラビア語 (Windows)
1257        windows-1257        バルト語 (Windows)
1258        windows-1258        ベトナム語 (Windows)
1361        Johab               韓国語 (Johab)
10000       macintosh           西ヨーロッパ言語 (Mac)
10001       x-mac-japanese      日本語 (Mac)
10002       x-mac-chinesetrad   繁体字中国語 (Mac)
10003       x-mac-korean        韓国語 (Mac)
10006       x-mac-greek         ギリシャ語 (Mac)
10007       x-mac-cyrillic      キリル語 (Mac)
10008       x-mac-chinesesimp   簡体字中国語 (Mac)
10010       x-mac-romanian      ルーマニア語 (Mac)
10017       x-mac-ukrainian     ウクライナ語 (Mac)
10029       x-mac-ce            中央ヨーロッパ語 (Mac)
10079       x-mac-icelandic     アイスランド語 (Mac)
10081       x-mac-turkish       トルコ語 (Mac)
10082       x-mac-croatian      クロアチア語 (Mac)
20000       x-Chinese-CNS       繁体字中国語 (CNS)
20127       us-ascii            US-ASCII
20261       x-cp20261           T.61
20290       IBM290              IBM EBCDIC (日本語カタカナ)
20866       koi8-r              キリル語 (KOI8-R)
20932       EUC-JP              日本語 (JIS 0208-1990 and 0212-1990)
20936       x-cp20936           簡体字中国語 (GB2312-80)
20949       x-cp20949           韓国語 Wansung
21027       x-cp21027           Ext Alpha Lowercase
21866       koi8-u              キリル語 (KOI8-R)
28591       iso-8859-1          西ヨーロッパ言語 (ISO)
28592       iso-8859-2          中央ヨーロッパ言語 (ISO)
28594       iso-8859-4          バルト語 (ISO)
28595       iso-8859-5          キリル語 (ISO)
28597       iso-8859-7          ギリシャ語 (ISO)
28599       iso-8859-9          トルコ語 (ISO)
28603       iso-8859-13         エストニア語 (ISO)
28605       iso-8859-15         ラテン語 9 (ISO)
50220       iso-2022-jp         日本語 (JIS)
50221       csISO2022JP         日本語 (JIS-Allow 1 byte Kana)
50222       iso-2022-jp         日本語 (JIS-Allow 1 byte Kana - SO/SI)
50225       iso-2022-kr         韓国語 (ISO)
50227       x-cp50227           簡体字中国語 (ISO-2022)
51932       euc-jp              日本語 (EUC)
51936       EUC-CN              簡体字中国語 (EUC)
51949       euc-kr              韓国語 (EUC)
52936       hz-gb-2312          簡体字中国語 (HZ)
54936       GB18030             簡体字中国語 (GB18030)
65000       utf-7               Unicode (UTF-7)
65001       utf-8               Unicode (UTF-8)


[日付を指定して曜日を取得する]
(Get-Date "2019/11/02").DayOfWeek
実行結果
    Saturday

実行結果を数値にする場合
    (Get-Date "2019/11/02").DayOfWeek.value__
この場合の実行結果
    6
(注)日曜日が0となる


[日付変数の使い方]
日付変数は DateTime オブジェクトとなる。
日付変数の作り方
    PS C:\Users\tad_i> $a = Get-Date "2018/12/06"
    PS C:\Users\tad_i> $a

    2018年12月6日 0:00:00

    PS C:\Users\tad_i>

今日の日付を取得するには
    PS C:\Users\tad_i> get-date

    2019年11月4日 15:29:00

日付変数の加算
    PS C:\Users\tad_i> $mar = Get-Date "2016/3/1 1:02:03"
    PS C:\Users\tad_i> $b = $mar.adddays(1)
    PS C:\Users\tad_i> $b

    2016年3月2日 1:02:03
    
    PS C:\Users\tad_i> $mar = Get-Date "2016/3/1 1:02:03"
    PS C:\Users\tad_i> $mar = $mar.adddays(10)
    PS C:\Users\tad_i> $mar

    2016年3月11日 1:02:03

日付変数を/で表示する
    PS C:\Users\tad_i> write-host $mar.tostring("yyyy/MM/dd")
    2016/02/11


[ディレクトリ(DIR)を削除する]
    remove-item -Path ディレクトリ名


[ディレクトリが空かどうかをチェックする]
    $directoryInfo = Get-ChildItem C:\temp | Measure-Object
    $directoryInfo.count #Returns the count of all of the files in the directory

    $ directoryInfo.count -eq 0の場合、ディレクトリは空です。


[PowerShellで外部プログラム（外部コマンド）を実行する]

PowerShellから外部プログラムを実行する場合は、

    直接exeを入力する
    &
    Start-Processコマンドレットを使用する

といった方法がる。

PS > notepad.exe test.txt
PS >

外部プログラムが空白を含むパスにある場合は、&を付ける（例ではPeaZipというアーカイバソフトを起動している）。

PS > & 'C:\Program Files\PeaZip\peazip.exe'
PS >

実行するとわかるが、すぐにプロンプトに制御が戻る。外部プログラムの完了を待ちたい場合は、

Start-Process -FilePath notepad.exe -ArgumentList test.txt -Wait

とStart-Processを-Waitを指定して実行すればよい。


[プロセスを止めずにStop-Processをシミュレートする]
PS C:\Users\tad_i> get-process pwsh | stop-process -whatif
What if: Performing the operation "Stop-Process" on target "pwsh (8772)".

PS C:\Users\tad_i> get-process pwsh | stop-process -Confirm

Confirm
Are you sure you want to perform this action?
Performing the operation "Stop-Process" on target "pwsh (8772)".
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"):


[文字列を16進数で表示]
引数に指定した文字列を16進数で表示するプログラムを作成しました。今回もEncodingクラスを
使用しています。GetEncodingメソッドでEncodingオブジェクトを取得することが出来ます。
引数に文字コードの名前を指定することが可能です。指定可能な名前の一覧は以下Microsoft 
MSDNのページにあります。
http://msdn.microsoft.com/ja-jp/library/system.text.encoding(VS.80).aspx
今回は文字コードとしてEUC-JP、shift_jis、iso-2022-jpを使います。
（注）UTF8はutf-8
指定方法は以下のようにします。
$aaa = [System.Text.encoding]::GetEncoding("EUC-JP")
$aaa = [System.Text.encoding]::GetEncoding("shift_jis")
$aaa = [System.Text.encoding]::GetEncoding("iso-2022-jp")
$aaaにはEncodingオブジェクトが入ります。
EncodingオブジェクトのGetBytesメソッドで設定されている文字コードを10進数で取得します。
取得した10進数をSystem.ConvertクラスのToStringメソッドで16進数に変換しています。

set-PSDebug -strict
# ---------------------------------------
# 文字コードを取得する
# 引数：コードを取得する文字列
# ---------------------------------------
Function GetCharCode{
    
    # 引数の取得
    param([string]$str)

    # 文字コードの設定
    $char_code_array = "EUC-JP","shift_jis","iso-2022-jp"
    
    # 何進数で表示するか
    [int]$out_number = 16

    # 文字コード分ループ
    foreach ( $char_code in $char_code_array ) {
    
        # 変数初期化
        $dec_codes = @{}
        $out_code_num = ""
    
        # encordingオブジェクト取得
        $encoding_wk = [System.Text.encoding]::GetEncoding($char_code)
        
        # 10進数の文字コード取得
        $dec_codes = $encoding_wk.getbytes($str)
        
        # 指定した進数に変換
        foreach ( $dec_code in $dec_codes ){
            $out_code_num += [System.Convert]::ToString($dec_code,$out_number) + " "
        }
        
        # 文字コード名取得
        $out_code_name = $encoding_wk.EncodingName
        
        # コードを大文字に変換
        $out_code_num = [String]$out_code_num.toupper()    
        
        # 画面出力
        write-Host $out_code_name
        write-Host $out_code_num
        write-Host ""
    }
}


[システムロケールの文字コードを取得する]
$encoding_wk = [System.Text.encoding]::GetEncoding($char_code)
write-host $encoding_WK.EncodingName

実行結果
Unicode (UTF-8)      ・・・Linux、アロケーションがUTF-8の場合
Japanese (Shift-JIS) ・・・Windows10 アロケーションがShift-JISの場合


[文字と16進数,10進数を相互に変換する]
$c = [char] 'が'
[System.Convert]::ToInt32($c).ToString("x")
304c
[System.Convert]::ToChar([System.Convert]::ToInt32("304c", 16))
が

$c = [char] '引'
[System.Convert]::ToInt32($c).ToString("D")
24341
[System.Convert]::ToChar([System.Convert]::ToInt32("24341", 10))
引


[今日の日付を得る get-date]
get-date -format "yyyy/MM/dd"


[エラー処理]
PowerShellのスクリプトででエラーが発生した場合にそのまま処理を継続したり、
終了させたりすることができます。
設定できるものとして以下があり、デフォルトはエラーが発生してもエラーを出力し、
そのままスクリプトを継続するようになっています。

    Stop:エラー メッセージが表示され、実行が停止されます。
    Inquire:エラー メッセージが表示され、続行するかどうかを確認するメッセージが表示されます。
    Continue (既定値):エラー メッセージが表示され、実行が続行されます。
    Suspend:さらなる調査のため、ワークフロー ジョブを自動的に中断します。
        調査の後で、ワークフローを再開できます。
    SilentlyContinue:影響を与えません。エラー メッセージは表示されず、
        中断されることなく実行が続行されます。

# 同じセッションの場合の挙動を変更。PowerShellを別途起動した場合にはデフォルト値に戻る
PS C:\Users\Administrator> $ErrorActionPreference
Continue
PS C:\Users\Administrator> $ErrorActionPreference = "Stop"
PS C:\Users\Administrator> $ErrorActionPreference
Stop


[PowerShell Windows形式⇔UNIX形式でのテキスト出力　改行コード調整]
PowerShellを使ってのWindows 形式の改行コード (CRLF) とUNIX形式の改行コード (LF) の相互変換の方法です。

Windows形式→UNIX形式
[string]::Join("`n",(Get-Content .\winText.txt))  | Set-Content .\unixText.txt

UNIX形式→Windows形式
[string]::Join("`r`n",(Get-Content .\unixText.txt))  | Set-Content .\winText.txt


[文の終了、セミコロン、文の継続 バックスラッシュ]
セミコロン（;）を使うと文の終了を明示し、複数の文をまとめることができる。
（例）
PS C:\Users\tad_i> 1;"test"
1
test

長くなりすぎないように１行を短く複数の行に分けて書くこともできる。
これには行継続という手法を用いる。
これにはハッシュタグ ` を用いる。


[二つのコロン :: の意味]
.NET クラスの静的プロパティ
    このサンプルでは、System.String クラスの Empty 静的プロパティを指定しています。
    [System.String]::Empty
    (結果)
    ABCXYZ

.NET クラスの静的メソッド
    このサンプルでは、System.String クラスの Concat 静的メソッドを実行しています。
    [System.String]::Concat("ABC", "XYZ")

プロバイダーを指定
します。これを使用すると、ドライブとして公開されていない場所にもアクセスすることが
できます。例えば、Registry プロバイダーは通常 HKLM と HKCU しか公開していませんが、
この指定方法を使うと、HKEY_CLASSES_ROOT にアクセスできます。
    dir Registry::HKEY_CLASSES_ROOT
    dir Variable::i


[シングルコロン : の意味]
ドライブを表す記号
このサンプルでは、Function ドライブに移動しています。
    cd Function:

スコープと変数の区切り記号
    このサンプルでは、global スコープの変数 a を表しています。
    $global:a = 1

ラベル
    このサンプルでは、Label1 ラベルを作成しています。
    :Label1
        while ($true){
            write-host $i
            for ($i = 1; $i -lt 1000; $i++){
                if ($i -eq 100){
                    break Label1
                }
            }
        }


[テキストファイルの最後に追加する Add-Content LFのみでの応用]
Add-Contentコマンドレットでテキストファイルの最後に追加します。
下記は「a.txt」ファイルの最後に「文末」を書き込みます。
Add-Content -LiteralPath .\a.txt -Value "文末"

-NoNewlineパラメーターを指定すると、改行を付けないで追加します。
Add-Content -LiteralPath .\a.txt -Value "文末" -NoNewline

-Forceパラメーターを指定すると読み込み専用属性でも書き込みます。
Add-Content -LiteralPath .\a.txt -Value "文末" -Force

下記はクリップボードのテキストを「a.txt」ファイルの最後に追加します。
Get-Clipboard | Add-Content -LiteralPath .\a.txt
