PowerShell はプログラミング言語の REPL みたいなもの
◆ コマンドプロンプトや bash の考えは捨てる
◆ devtools のコンソールや python, node, csi コマンドみたいなものとして考えるとわかりやすい
◆ devtools のコンソールや python, node, csi コマンドみたいなものとして考えるとわかりやすい
PowerShell って使い方がよくわからないしコマンドプロンプトのほうが使いやすいというスタイルでしたが あることに気づくとけっこう使いやすいものになりました
PowerShell ってコマンドプロンプトに近いもので Windows 10 ではコマンドプロンプトが PowerShell に置き換えられてます
さらに Shell という名前からも Linux などで使える bash や fish とかそういう系統のツールの仲間って感じがします
なので それらと同じようにプログラムの名前とそれに渡すオプションを書いたコマンドを実行するものって思っていました
しかし PowerShell はそういった Shell の仲間ではなくプログラミング言語の REPL です
JavaScript のコンソールとか C# の csi と同じものと思うと理解しやすくなります
.NET ということもあって csi がすごく近いです
わかりやすいのがこれ
四則演算とか文字列結合とかメソッド呼び出しが使えます
これを見るだけで親近感が一気にわきました
コマンドプロンプトや bash みたいなものとして扱おうとしたので意味不明だったんです
.NET の新しいプログラミング言語の 1 つと考えるだけですごく印象が変わりました
変数も使えます
PHP みたいに $ を付ける必要がありますけど
パースの仕方が C# などに近いので bash みたいに = の前後でスペースいれるとダメみたいな制限はないです
文字列は "" と '' があって変数展開の有無が違います
これは bash ぽいですね
変数には大文字小文字の区別がありません
数値や文字列はリテラルで書けますが true/false/null はそのままリテラルでは書けません
$true や $false と言った変数に入ってるのでそれを使うことになります
true/false がリテラルじゃなくて最初から用意されてる変数を参照してるだけって何かの言語でみた気がするのですがなんだっけ……
null は何も表示されません
空文字の場合は空行が出るので判別は可能です
$true を上書きしたらどうなるの?と思いましたが読み取り専用になっていました
ただ null は特殊で代入できるのに変化しないという挙動です
strict じゃない JavaScript でよく見るやつです
また 初期化してない変数へのアクセスはエラーではなく null になっています
if に使いそうな == や < や && はちょっと C# とは違います
-eq や -lt や -and になります
boolean 値の反転はおなじみの ! でできます
if 文はこんな感じです
C# と違って 条件式のあとは複文の {} が必須です
さらに嬉しいことにこの if は式になっていて結果を代入できます
関数呼び出しはメソッドなら C# と同じように .MethodName() 形式です
プロパティも同様に . とプロパティ名でアクセスできます
ここも大文字小文字の区別はありません
static 関数の場合は [] の中にクラス名を指定してその後で :: をつけてメソッド名を呼び出します
new でオブジェクトを作りたいときは New-Object を使います
クラス名と引数をスペース区切りで書きます
ジェネリック型を使うときは [] で型を指定します
New-Object のような機能はコマンドレットと呼ばれていて PowerShell には多くのコマンドレットが用意されています
時刻取得なら Get-Date です
結果の代入も可能です
ファイルの作成には New-Item です
コマンドレットなどのコマンド一覧は get-command で見れます
Alias, Function, Cmdlet があります
コマンドプロンプトと同じように cd でディレクトリを移動できますが これはエイリアスで cd を使うと Set-Location コマンドレットを実行しています
同じように dir や ls では Get-ChildItem コマンドレットが実行されています
Get-Help を使えばコマンドレットの使い方の表示ができます
他にも関数やクラスを定義したり パイプを使ったり C# で作った dll をロードしたり色々できるのですが この辺までにしておきます
用途的に C# でするような複雑なことはしないと思いますし 変数の扱いや関数・メソッドの呼び出しがわかれば十分かもしれません
せっかく .NET なので複雑なことをしたいなら無理に PowerShell で頑張るよりも使い慣れた C# で書いてその関数を呼び出すだけってこともできますし
C# と連携を考えてると使えるのは .NET Framework だけで .NET Core で作った dll はダメなのかなって思いましたが最近は PowerShell も .NET Core 版が出てたのでした
https://github.com/PowerShell/PowerShell
しかもこっちに移行で古い方はもう更新されないとか
コマンドプロンプトから PowerShell メインに移るのならこっちを入れておいたほうがいいかもしれませんね
Core のほうはバージョン 7 が rc3 まででてるので 7 のリリースが近そうです
それに対して Windows7 の標準のものは 2.0 なのでかなり差があります
PowerShell ってコマンドプロンプトに近いもので Windows 10 ではコマンドプロンプトが PowerShell に置き換えられてます
さらに Shell という名前からも Linux などで使える bash や fish とかそういう系統のツールの仲間って感じがします
なので それらと同じようにプログラムの名前とそれに渡すオプションを書いたコマンドを実行するものって思っていました
しかし PowerShell はそういった Shell の仲間ではなくプログラミング言語の REPL です
JavaScript のコンソールとか C# の csi と同じものと思うと理解しやすくなります
.NET ということもあって csi がすごく近いです
わかりやすいのがこれ
四則演算とか文字列結合とかメソッド呼び出しが使えます
PS C:\Users\winuser> 1 + 3
4
PS C:\Users\winuser> 3 / 2
1.5
PS C:\Users\winuser> "foo" + "bar"
foobar
PS C:\Users\winuser> "abcd".SubString(2)
cd
これを見るだけで親近感が一気にわきました
コマンドプロンプトや bash みたいなものとして扱おうとしたので意味不明だったんです
.NET の新しいプログラミング言語の 1 つと考えるだけですごく印象が変わりました
変数も使えます
PHP みたいに $ を付ける必要がありますけど
PS C:\Users\winuser> $foo = 1
PS C:\Users\winuser> $bar = $foo * 10
PS C:\Users\winuser> $bar
10
パースの仕方が C# などに近いので bash みたいに = の前後でスペースいれるとダメみたいな制限はないです
文字列は "" と '' があって変数展開の有無が違います
これは bash ぽいですね
PS C:\Users\winuser> "[$bar]"
[10]
PS C:\Users\winuser> '[$bar]'
[$bar]
変数には大文字小文字の区別がありません
PS C:\Users\winuser> $BAR
10
PS C:\Users\winuser> $Bar
10
数値や文字列はリテラルで書けますが true/false/null はそのままリテラルでは書けません
$true や $false と言った変数に入ってるのでそれを使うことになります
true/false がリテラルじゃなくて最初から用意されてる変数を参照してるだけって何かの言語でみた気がするのですがなんだっけ……
PS C:\Users\winuser> $true
True
PS C:\Users\winuser> $false
False
PS C:\Users\winuser> $null
null は何も表示されません
空文字の場合は空行が出るので判別は可能です
$true を上書きしたらどうなるの?と思いましたが読み取り専用になっていました
PS C:\Users\winuser> $true = "a"
変数 true は読み取り専用または定数であるため、上書きできません。
ただ null は特殊で代入できるのに変化しないという挙動です
strict じゃない JavaScript でよく見るやつです
PS C:\Users\winuser> $null = 10
PS C:\Users\winuser> $null
また 初期化してない変数へのアクセスはエラーではなく null になっています
PS C:\Users\winuser> $UNDEFINED_VALUE
PS C:\Users\winuser> $UNDEFINED_VALUE -eq $null
True
if に使いそうな == や < や && はちょっと C# とは違います
-eq や -lt や -and になります
PS C:\Users\winuser> 3 -gt 2
True
PS C:\Users\winuser> -1 -gt 1
False
PS C:\Users\winuser> 3 -lt 2
False
PS C:\Users\winuser> -1 -lt 1
True
PS C:\Users\winuser> "a" -eq "a"
True
PS C:\Users\winuser> "0" -eq 0
True
PS C:\Users\winuser> $true -and $true
True
PS C:\Users\winuser> $true -and $false
False
PS C:\Users\winuser> $true -or $false
True
PS C:\Users\winuser> $false -or $false
False
boolean 値の反転はおなじみの ! でできます
if 文はこんな感じです
PS C:\Users\winuser> if ($true) { 1 } else { 2 }
1
PS C:\Users\winuser> if ($false) { 1 } else { 2 }
2
C# と違って 条件式のあとは複文の {} が必須です
さらに嬉しいことにこの if は式になっていて結果を代入できます
PS C:\Users\winuser> $a = if ($true) { 10 }
PS C:\Users\winuser> $a
10
関数呼び出しはメソッドなら C# と同じように .MethodName() 形式です
プロパティも同様に . とプロパティ名でアクセスできます
ここも大文字小文字の区別はありません
PS C:\Users\winuser> "abcd".Length
4
PS C:\Users\winuser> "abcd".EndsWith("d")
True
PS C:\Users\winuser> $true.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Boolean System.ValueType
PS C:\Users\winuser> 10L.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int64 System.ValueType
static 関数の場合は [] の中にクラス名を指定してその後で :: をつけてメソッド名を呼び出します
PS C:\Users\winuser> [Console]::WriteLine("text")
text
PS C:\Users\winuser> [Math]::Pow(2, 1024)
+∞
PS C:\Users\winuser> [Math]::Pow(2, 16)
65536
PS C:\Users\winuser> [String]::Empty -eq ""
True
new でオブジェクトを作りたいときは New-Object を使います
クラス名と引数をスペース区切りで書きます
PS C:\Users\winuser> New-Object DateTime
0001年1月1日 0:00:00
PS C:\Users\winuser> $uri = New-Object System.Uri "http://example.com/foo/bar.html"
PS C:\Users\winuser> $uri
AbsolutePath : /foo/bar.html
AbsoluteUri : http://example.com/foo/bar.html
Authority : example.com
Host : example.com
HostNameType : Dns
IsDefaultPort : True
IsFile : False
IsLoopback : False
IsUnc : False
LocalPath : /foo/bar.html
PathAndQuery : /foo/bar.html
Port : 80
Query :
Fragment :
Scheme : http
OriginalString : http://example.com/foo/bar.html
DnsSafeHost : example.com
IsAbsoluteUri : True
Segments : {/, foo/, bar.html}
UserEscaped : False
UserInfo :
PS C:\Users\winuser> $uri.Port
80
PS C:\Users\winuser> $uri.LocalPath
/foo/bar.html
PS C:\Users\winuser> $r = New-Object System.Random
PS C:\Users\winuser> $r.Next()
200661696
PS C:\Users\winuser> $r.Next()
1485192138
PS C:\Users\winuser> $r.Next()
886792691
ジェネリック型を使うときは [] で型を指定します
PS C:\Users\winuser> $nums = New-Object System.Collections.Generic.List[int]
PS C:\Users\winuser> $nums.Add(1)
PS C:\Users\winuser> $nums.Add(2)
PS C:\Users\winuser> $nums.Add(3)
PS C:\Users\winuser> $nums
1
2
3
New-Object のような機能はコマンドレットと呼ばれていて PowerShell には多くのコマンドレットが用意されています
時刻取得なら Get-Date です
結果の代入も可能です
PS C:\Users\winuser> get-date
2020年2月23日 22:37:02
PS C:\Users\winuser> $a = Get-Date
PS C:\Users\winuser> $a
2020年2月23日 22:37:52
ファイルの作成には New-Item です
PS C:\Users\winuser> new-item "test123.txt" -type file
ディレクトリ: C:\Users\winuser
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2020/02/23 22:36 0 test123.txt
コマンドレットなどのコマンド一覧は get-command で見れます
PS C:\Users\winuser> Get-Command
CommandType Name Definition
----------- ---- ----------
Alias % ForEach-Object
Alias ? Where-Object
Function A: Set-Location A:
Alias ac Add-Content
Cmdlet Add-Computer Add-Computer [-DomainName] <String> [-Credential...
Cmdlet Add-Content Add-Content [-Path] <String[]> [-Value] <Object[...
Cmdlet Add-History Add-History [[-InputObject] <PSObject[]>] [-Pass...
Cmdlet Add-Member Add-Member [-MemberType] <PSMemberTypes> [-Name]...
Cmdlet Add-PSSnapin Add-PSSnapin [-Name] <String[]> [-PassThru] [-Ve...
Cmdlet Add-Type Add-Type [-TypeDefinition] <String> [-Language <...
Alias asnp Add-PSSnapIn
Function B: Set-Location B:
Function C: Set-Location C:
Alias cat Get-Content
Alias cd Set-Location
Function cd.. Set-Location ..
Function cd\ Set-Location \
Alias chdir Set-Location
(略)
Alias, Function, Cmdlet があります
コマンドプロンプトと同じように cd でディレクトリを移動できますが これはエイリアスで cd を使うと Set-Location コマンドレットを実行しています
同じように dir や ls では Get-ChildItem コマンドレットが実行されています
PS C:\Users\winuser> get-command dir,ls
CommandType Name Definition
----------- ---- ----------
Alias dir Get-ChildItem
Alias ls Get-ChildItem
Get-Help を使えばコマンドレットの使い方の表示ができます
PS C:\Users\winuser> get-help set-location
名前
Set-Location
概要
現在の作業場所を、指定された場所に設定します。
構文
Set-Location [-LiteralPath] <string> [-PassThru] [-UseTransaction] [<CommonParameters>]
Set-Location [[-Path] <string>] [-PassThru] [-UseTransaction] [<CommonParameters>]
Set-Location [-StackName <string>] [-PassThru] [-UseTransaction] [<CommonParameters>]
(略)
他にも関数やクラスを定義したり パイプを使ったり C# で作った dll をロードしたり色々できるのですが この辺までにしておきます
用途的に C# でするような複雑なことはしないと思いますし 変数の扱いや関数・メソッドの呼び出しがわかれば十分かもしれません
せっかく .NET なので複雑なことをしたいなら無理に PowerShell で頑張るよりも使い慣れた C# で書いてその関数を呼び出すだけってこともできますし
C# と連携を考えてると使えるのは .NET Framework だけで .NET Core で作った dll はダメなのかなって思いましたが最近は PowerShell も .NET Core 版が出てたのでした
https://github.com/PowerShell/PowerShell
しかもこっちに移行で古い方はもう更新されないとか
コマンドプロンプトから PowerShell メインに移るのならこっちを入れておいたほうがいいかもしれませんね
Core のほうはバージョン 7 が rc3 まででてるので 7 のリリースが近そうです
それに対して Windows7 の標準のものは 2.0 なのでかなり差があります