PowerShell Advent Calendar 2015 3日目の記事です。
基本的にはabout_OperatorsやPowerShellの言語仕様書(PowerShell 2.0、PowerShell 3.0)を見ればわかる話なのですが、一覧で参照したかったのと、PowerShellには一見演算子に見えない特殊な演算子が結構ありその解説をしたくなったので本エントリを書きました。
一部の内容についてはWindows PowerShell in Actionを参考にしています。
字数の都合、詳細まで説明するのは難しいので、基本的な説明と個人的に気になる部分について解説を入れる形としています。
算術演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| + | 1 + 2 | 加算、プラス |
| - | 1 - 2 | 減算、マイナス |
| * | 1 * 2 | 乗算 |
| / | 10 / 2 | 除算 |
| % | 10 % 3 | 余剰 |
最初は算術演算子から。
+と-は単項演算子としても使用可能です。
端数処理は銀行丸めになります。*1
また、配列と文字列については+、*演算子の内容がオーバーロードされており、
- 配列の
+は要素の追加、*は要素の繰り返し - 文字列の
+は結合、*は文字列の繰り返し
になっています。
# 配列の加算・乗算 (1,2,3) + 4 => (1,2,3,4) (1,2,3) * 4 => (1,2,3,1,2,3,1,2,3,1,2,3) # 文字列の加算・乗算 "abc" + "d" => "abcd" "abc" * 2 => "abcabc"
その他詳細はabout_Arithmetic_Operatorsを参照してください。
ビット演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| -band | 10 -band 3 | AND |
| -bor | 10 -bor 3 | OR |
| -bxor | 10 -bxor 3 | XOR |
| -bnot | -bnot 100 | NOT |
| -shl | 100 -shl 2 | 左シフト(PowerShell3.0より) |
| -shr | 100 -shr 2 | 右シフト(PowerShell3.0より) |
ヘルプ上は比較演算子になっているのですが、本エントリではビット演算もここで説明します。
PowerShell 3.0からシフト演算ができる様になっています。
ビット演算の詳細はabout_Comparison_Operatorsを参照してください。
代入演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| = | $a = 123 | 代入 |
| += | $a += 123 | 加算して代入 |
| -= | $a -= 123 | 減算して代入 |
| *= | $a *= 123 | 乗算して代入 |
| /= | $a /= 123 | 除算して代入 |
| %= | $a %= 3 | 余剰を求めて代入 |
| ++ | ++$v, $v++ | インクリメント |
| -- | --$v, $v-- | デクリメント |
代入演算子です。
インクリメント・デクリメントについては前置または後置することができます。
詳細はabout_Assignment_Operatorsを参照してください。
比較演算子(1)
| 演算子 | 用例 | 内容 |
|---|---|---|
| -eq (-ieq) |
"abc" -eq "ABC" | 等しいか比較 |
| -ceq | "abc" -ceq "ABC" | 等しいか比較(大文字小文字を区別する) |
| -ne (-ine) |
"abc" -ne "ABC" | 等しくないか比較 |
| -cne | "abc" -cne "ABC" | 等しくないか比較(大文字小文字を区別する) |
| -gt (-igt) |
8 -gt 6 | より大きいか(>)比較 |
| -cgt | 8 -cgt 6 | より大きいか(>)比較(大文字小文字を区別する) |
| -ge (-ige) |
8 -ge 6 | 以上か(>=)比較 |
| -cge | 8 -cge 6 | 以上か(>=)比較(大文字小文字を区別する) |
| -lt (-ilt) |
6 -lt 8 | より小さいか(<)比較 |
| -clt | 6 -clt 8 | より小さいか(<)比較(大文字小文字を区別する) |
| -le (-ile) |
6 -le 8 | 以下か(<=)比較 |
| -cle | 6 -cle 8 | 以下か(<=)比較(大文字小文字を区別する) |
基本的な比較演算子です。
文字列の比較の場合は原則として大文字・小文字の区別はされず、大文字・小文字を区別して比較する場合は-cほげほげ演算子を使います。
その他細かい点はabout_Comparison_Operatorsや以下の記事を参照してください。
比較演算子(2) (LikeとMatch)
| 演算子 | 用例 | 内容 |
|---|---|---|
| -like (-ilike) |
"PowerShell" -like "*shell" | ワイルドカードを使ったLike検索に一致するか比較 |
| -clike | "PowerShell" -clike "*shell" | ワイルドカードを使ったLike検索に一致するか比較 (大文字小文字を区別する) |
| -notlike (-inotlike) |
"PowerShell" -notLike "*shell" | ワイルドカードを使ったLike検索に一致しないか比較 |
| -cnotlike | "PowerShell" -cnotLike "*shell" | ワイルドカードを使ったLike検索に一致しないか比較 (大文字小文字を区別する) |
| -match (-imatch) |
$l -match ".shell" | 指定の正規表現に一致するか比較 |
| -cmatch | "PowerShell" -cmatch ".shell" | 指定の正規表現に一致するか比較 (大文字小文字を区別する) |
| -notmatch (-inotmatch) |
"PowerShell" -notmatch ".shell" | 指定の正規表現に一致しないか比較 |
| -cnotmatch | "PowerShell" -cnotmatch ".shell" | 指定の正規表現に一致しないか比較 (大文字小文字を区別する) |
-like演算子ではワイルドカード(*、?、[])を使った検索、-match演算子では正規表現を使った検索による比較が可能です。
比較するのは文字列のみで、左辺が配列の場合は右辺に一致する要素を検索します。
また、-matchの場合は検索してマッチした結果が$Matches自動変数に設定されます*2。
# 左辺が配列の場合は右辺に一致する要素を検索 PS C:\> "windows", "power", "shell" -match "s" windows shell # 左辺が配列でない場合、-match検索の結果は$Matches自動変数に設定される PS C:\> "windows power shell" -match "(ow)" True PS C:\> $Matches Name Value ---- ----- 1 ow 0 ow
全てをここで説明するのはつらいので詳細はabout_Comparison_Operatorsを確認してみてください。
比較演算子(3) (包含演算子)
| 演算子 | 用例 | 内容 |
|---|---|---|
| -contains (-icontains) |
("a","b","c") -contains "A" | 配列に指定の要素が含まれるか比較 |
| -ccontains | ("a","b","c") -ccontains "A" | 配列に指定の要素が含まれるか比較 (大文字小文字を区別する) |
| -notcontains (-inotcontains) |
("a","b","c") -notcontains "A" | 配列に指定の要素が含まれないか比較 |
| -cnotcontains | ("a","b","c") -cnotcontains "A" | 配列に指定の要素が含まれないか比較 (大文字小文字を区別する) |
| -in (-iin) |
"A"-in ("a","b","c") | 配列に指定の要素が含まれるか比較 (PowerShell3.0より) |
| -cin | "A"-cin ("a","b","c") | 配列に指定の要素が含まれるか比較 (大文字小文字を区別する)(PowerShell3.0より) |
| -notin (-inotin) |
"A"-notin ("a","b","c") | 配列に指定の要素が含まれないか比較 (PowerShell3.0より) |
| -cnotin | "A"-cnotin ("a","b","c") | 配列に指定の要素が含まれないか比較 (大文字小文字を区別する)(PowerShell3.0より) |
配列に要素が含まれるか比較する包含演算子です。
-inはPowerShell 3.0から導入され、-containsの逆の記法になります。
about_Comparison_Operatorsに記載されていますが、等価比較には参照の等価性が使用されます。
以下の例の様な結果になる点は注意が必要です。
# 同じ参照ではないのでFalseを返す PS C:\> ("abc", "def"),"ghi" -contains ("abc", "def") False # 同じ参照なのでTrueを返す PS C:\> $a = "abc", "def" PS C:\> $a, "ghi" -Contains $a True
比較演算子(4) (置換演算子、分割演算子、結合演算子)
| 演算子 | 用例 | 内容 |
|---|---|---|
| -replace (-ireplace) |
"PowerShell" -replace "s", " " | 文字列の置換を行う |
| -creplace | "PowerShell" -creplace "s", " " | 文字列の置換を行う(大文字小文字を区別する) |
| -split (-isplit) |
"PowerShell" -split "s" | 文字列を分割する |
| -csplit | "PowerShell" -csplit "s" | 文字列を分割する(大文字小文字を区別する) |
| -join | -join ( "Power", "Shell") | 文字列を結合する |
文字列操作を行う演算子です。
-replaceでは正規表現を使った置換ができ、.NETの置換パターンがそのまま使えます。
-splitと-joinは単項または二項演算子として使用可能で数多くのオプションがあります。
以下にいくつか使用例を記載します。
# -replace演算子では正規表現がつかえる "Analogous" -replace "[aeiou]",'$&$&' # -split 単項演算子 - デリミタはスペースとなる -split "Power Shell" => @("Power", "Shell") # -split 二項演算子 - デリミタを指定できる "Power/Shell" -split "/" => @("Power", "Shell") # デリミタを()で囲むと囲んだ文字も結果に含めることができる "Power/Shell" -split "(/)" => @("Power", "/", "Shell") # デリミタの後に最大分割数を指定することもできる "Windows/Power/Shell" -split "/", 2 => @("Windows", "Power/Shell") # 最大分割数を指定した場合はオプションを指定することができる "This.is.a.test" -split ".", 0, "simplematch" # -join 単項演算子 -join @("Power", "Shell") => "PowerShell" # -join 二項演算子 - 結合する際に間に挟む文字を指定できる "Power", "Shell" -join "☆" => "Power☆Shell" # ※演算子の優先順位に注意が必要 -join "a", "b", "c" => (-join "a"), "b", "c" => @("a", "b", "c")
全てをここで説明するのはつらいので詳細はabout_Split、about_Joinを確認してみてください。
型演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| -is | (Get-Date) -is [Datetime] | 値の型が一致するか比較 |
| -isnot | (Get-Date) -isnot [Datetime] | 値の型が一致しないか比較 |
| -as | "2015/12/31" -as [DateTime] | 値を指定の型にキャストする |
.NETの型を扱う演算子が型演算子として区分されています。
-as演算子はC#のそれと同じですが、PowerShellの場合は値型にも適用することができます。
また、型の指定は通常[型名]ですが、"型名"で指定することもできます。
# PowerShellの-as演算子は値型にも適用することができる PS C:\> 1 -as [int] 1
詳細はabout_Type_Operatorsで確認してください。
論理演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| -and | (1 -eq 1) -and (1 -eq 2) | 論理積 |
| -or | (1 -eq 1) -or (1 -eq 2) | 論理和 |
| -xor | (1 -eq 1) -xor (1 -eq 2) | 排他的論理和 |
| -not (!) | -not (1 -eq 1) | 否定 |
論理演算子です。否定は!も使えます。
詳細はabout_Logical_Operatorsで確認してください。
リダイレクト演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| > | ls *.ps1 > Scripts.txt | 標準ストリームをリダイレクト |
| >> | ls *.ps1 >> Scripts.txt | 標準ストリームをリダイレクト(追記) |
| 2> | ls *.ps1 2> Scripts.txt | エラーストリームをリダイレクト |
| 2>> | ls *.ps1 2>> Scripts.tx2t | エラーストリームをリダイレクト(追記) |
| 2>&1 | ls *.ps1 2>&1 | エラーストリームを標準ストリームにリダイレクト |
| 3> | Write-Warning "Test!" 3> Warnings.txt | 警告ストリームをリダイレクト (PowerShell3.0より) |
| 3>> | lWrite-Warning "Test!" 3>> Warnings.txt | 警告ストリームをリダイレクト(追記) (PowerShell3.0より) |
| 3>&1 | Write-Warning "Test!" 3>&1 | 警告ストリームを標準ストリームにリダイレクト (PowerShell3.0より) |
| 4> | Import-Module * -Verbose 4> Verbose.txt | 詳細ストリームをリダイレクト (PowerShell3.0より) |
| 4>> | Import-Module * -Verbose 4>> Verbose.txt | 詳細ストリームをリダイレクト(追記) (PowerShell3.0より) |
| 4>&1 | Import-Module * -Verbose 4>&1 | 詳細ストリームを標準ストリームにリダイレクト (PowerShell3.0より) |
| 5> | Write-Debug "Starting" 5> Debug.txt | デバッグストリームをリダイレクト (PowerShell3.0より) |
| 5>> | Write-Debug "Starting" 5>> Debug.txt | デバッグストリームをリダイレクト(追記) (PowerShell3.0より) |
| 5>&1 | Write-Debug "Starting" 5>&1 | デバッグストリームを標準ストリームにリダイレクト (PowerShell3.0より) |
| 6> | Write-Host "Test" 6> Info.txt | 情報ストリームをリダイレクト (PowerShell5.0より) |
| 6>> | Write-Host "Test" 6>> Info.txt | 情報ストリームをリダイレクト(追記) (PowerShell5.0より) |
| 6>&1 | Write-Host "Test" 6>&1 | 情報ストリームを標準ストリームにリダイレクト (PowerShell5.0より) |
| *> | - | すべてのストリームをリダイレクト (PowerShell3.0より) |
| *>> | - | すべてのストリームをリダイレクト(追記) (PowerShell3.0より) |
| *>&1 | - | すべてのストリームを標準ストリームにリダイレクト (PowerShell3.0より) |
リダイレクトについては、
で書いた様にPowerShellでは1>~6>までのストリームがありそれぞれにリダイレクト演算子があります。
3>~5>はPowerShell 3.0から6>はPowerShell 5.0から使用することができます。
ちなみにリダイレクトに関連する他の演算子<、n>&2 (n=1,3,4,5,6,*)、||、&&は予約語となっていますが機能は実装されておらず指定するとエラーになります。
about_Redirectionも併せて参照してください。
特殊な演算子
ここからが本エントリの本番といった感じです。
PowerShellでは一見わかりにくい演算子が結構あり、以下に個別に記載していきます。
| パイプライン演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| | | 123 | Get-Member | コマンドの出力をパイプする |
まずはパイプラインから。
パイプラインはPowerShellのキモですが、ここでは特に説明することはないです。
@() 配列部分式演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| @() | @(Get-WMIObject win32_logicalDisk) | @()内部の文の結果を配列にする |
@()演算子は()内部で評価された文の結果を配列に変換します。
文の評価結果が単一の値の場合は要素数1の配列にします。
イメージとしては後述の$()部分式演算子を使った[Object[]]$( 文 )と同等な感じです。
# 文の評価結果が単一の値の場合は要素数1の配列に変換する PS C:\> $array = @(123) PS C:\> $array.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array PS C:\> $array.Count 1
, コンマ演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| , | 1, 2 | 配列を生成する |
コンマ演算子は単項または二項演算子として使用することができ配列を生成します。
@()演算子と似た動作をしますがこちらの場合は配列化+要素の追加といったイメージです。
# 単項演算子ととして使用した場合は要素数1の配列を生成する PS C:\> $array = , 123 PS C:\> $array.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array PS C:\> $array.Count 1 # 二項演算子として使用した場合は指定した要素数の配列を生成する PS C:\> $array = 1 , 2 , 3 PS C:\> $array.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array PS C:\> $array.Count 3
.. 範囲演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| .. | 1 .. 10 | Int型の配列を生成する |
..演算子は連続する値のInt型配列を生成します。
Int型以外の型を指定した場合はInt型への変換を試みた上で配列を生成します。
昇順または降順を選ぶことができます。
# 昇順 1 .. 5 => (1, 2, 3, 4, 5) # 降順 5 .. 1 => (5, 4, 3, 2, 1)
【2017/12/22追記】
2018年1月リリース予定のPowerShell 6.0で、..演算子にChar型の値を指定できる様になります。
# PowerShell 6.0より 'a'..'e' => ([char]'a', [char]'b', [char]'c', [char]'d', [char]'e')
細かい話はこちらのエントリをご覧ください。
-f 書式設定演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| -f | "現在の時刻は {0:HH:mm:ss} です。" -f (Get-Date) | 文字列のフォーマットを行う |
文字列のフォーマットを行う演算子です。
書式の指定は.NETの書式と同じになります。
PS C:\> "現在の時刻は {0:HH:mm:ss} です。" -f (Get-Date) 現在の時刻は 20:32:35 です。
. ドット ソース演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| . | . .\Sample.ps1 | 指定のスクリプトファイルを読み込む |
Unix系シェルのsourceまたは.コマンドと同様のものです。
読み込まれたスクリプトのスコープは.が呼ばれたスコープになります。
& 呼び出し演算子(起動演算子)
| 演算子 | 用例 | 内容 |
|---|---|---|
| & | & "get-executionpolicy" | コマンド、スクリプト、またはスクリプトブロックを実行する。 |
コマンド、スクリプト、またはスクリプトブロックを実行します。
Invoke-ExpressionとInvoke-Commandを合わせた様なものですがローカル専用です。
# 文字列をパースして実行 PS C:\> & "ls" # スクリプトブロックを実行 PS C:\> & { ls } # コマンドオブジェクトを実行 PS C:\> $cmd = Get-Command -Name Get-ChildItem PS C:\> & $cmd
$( ) 部分式演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| $() | $($x * 23) | ()内の文を評価した結果を返す |
()内の文を評価した結果を返します。
いまいち使いどころがみえないのですが、この演算子は文字列内で使うのが良さそうです。
詳細はこの記事をみてください。
# $()演算子は文字列内の文を評価できる PS C:\> $Word = "文字列" PS C:\> Write-Host "$Word は$( $Word.Length )文字です。" 文字列 は3文字です。
[ ] キャスト演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| [] | [datetime]'2015/12/31' | 指定した型にキャストする |
[型名]値の形式でキャストすることができます。
[ ] インデックス演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| [] | $a[1] | 配列の要素を指定 |
$変数[式]の形式でインデックスの要素を取得できます。
[]で指定するのはあくまで式であり、配列であれば整数または配列、ハッシュテーブルであれば文字列または配列を指定することができます。
配列が指定された場合は配列内の要素に一致する要素を取得する所謂スライスをすることができます。
# 通常のインデックス指定 PS C:\> $array = @(1,2,3,4,5) PS C:\> $array[1] 2 # インデックス内に配列が来た場合はスライスすることができる # $array[@(1,2)] => @($array[1]) + @($array[2])なイメージ PS C:\> $array[@(1,2)] 2 3 # 配列であれば良いので以下の様な指定方法も可能 PS C:\> $array[1,2] 2 3 PS C:\> $array[1..2] 2 3
. プロパティ逆参照演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| . | $Word.Length | オブジェクトのプロパティとメソッドにアクセスする |
MSDNの訳がプロパティ逆参照演算子となっていますが、英語名はProperty dereference operatorです。
dereferenceの日本語訳には諸派あるみたいなのであまり深く触れませんが、個人的にはプロパティデリファレンス演算子の方が適当な気がしています。
機能としてはプロパティやメソッド呼び出しのための演算子でとくに深く考える必要はありません。
この演算子で呼び出すプロパティやメソッドの指定に変数や部分式を使うことができます。
# 普通のプロパティ呼び出し PS C:\> "PowerShell".Length 10 # プロパティ名の指定に変数や部分式を使うことができる PS C:\> $PropertyName = "Length" PS C:\> "PowerShell".$PropertyName 10 PS C:\> "PowerShell".$( "Len" + "gth" ) 10 # パラメータの解決はできないのでメソッドには使えない PS C:\> $MethodName = "SubString(0,5)" PS C:\> "PowerShell".$MethodName PS C:\> # でも以下の様な呼び出しは可能 PS C:\> $MethodName = "SubString" PS C:\> "PowerShell".$MethodName(0,5) Power
:: 静的メンバー演算子
| 演算子 | 用例 | 内容 |
|---|---|---|
| :: | [datetime]::Now | クラスのスタティックなプロパティとメソッドにアクセスする |
::でクラスのスタティックなプロパティとメソッドにアクセスできます。
この演算子も呼び出すプロパティやメソッドの指定に変数や部分式を使うことができます。
# .演算子同様にプロパティ名の指定に変数や部分式を使うことができる PS C:\> $PropertyName = "E" PS C:\> [Math]::$PropertyName 2.71828182845905 PS C:\> [Math]::$([char]69) 2.71828182845905 # メソッドの指定も同様 PS C:\> $MethodName = "Abs" PS C:\> [Math]::$MethodName(-123) 123
補足
三項演算子
PowerShellではこれまで三項演算子はサポートされていなかったのですが、PowerShell 7 Preview.4より試験的な機能として三項演算子が導入されています。
C#と同様の<condition> ? <consequent> : <alternative>の構文が利用可能です。
# PowerShell 7 Preview.4以降で利用可能 $IsWindows ? "yes" : "no" $IsLinux ? "yes" : "no"
導入の経緯についてはこちらのエントリをご覧ください。
Pipeline Chain Operators (&& と ||)
PowerShell 7 Preview.5より試験的な機能として&&と||の2つの演算子が導入されています。
&&演算子は前のコマンド(左オペランド)の結果が正常終了であれば後続の処理(右オペランド)を実行します。
# 前のコマンドが正常終了であれば後続の処理が実行される Write-Output "Hello" && Write-Output "World" # 前のコマンドが異常終了(下記は Write-Outpt と不正なコマンドレット名)であれば後続の処理は実行されない Write-Outpt "Hello" && Write-Output "World"
||演算子は&&とは逆に前のコマンド(左オペランド)の結果が正常終了でなければ後続の処理(右オペランド)を実行します。
# 前のコマンドが正常終了であれば後続の処理は実行されない Write-Output "Hello" || Write-Output "World" # 前のコマンドが異常終了(下記は Write-Outpt と不正なコマンドレット名)であれば後続の処理が実行される Write-Outpt "Hello" || Write-Output "World"
詳細は以下のエントリをご覧ください。
NULL合体演算子 (?? と ??=)
PowerShell 7 Preview.5より試験的な機能として??と??=の2つの演算子が導入されています。
NULL合体演算子(??)は値がNULLでない場合左オペランドの値を返し、NULLの場合は右オペランドの値を返します。
# 左オペランドがNULLでない場合は、その値を返す $left="left is not null." $right=$null $left ?? $right # 右オペランドの値はNULLかどうかは関係ない $right="right is not null." $left ?? $right # 左オペランドがNULLの場合は右オペランドの値を返す $left=$null $left ?? $right
NULL合体割り当て演算子(??=)は左オペランドがNULLの場合のみ、右オペランドの値を代入します。
# 左オペランドがNULLの場合のみ代入可能 $right="value1" $left ??= $right # 左オペランドは先の代入でNULLでないため更新できない $right="value2" $left ??= $right
詳細は以下のエントリをご覧ください。
最後に
PowerShellの演算子について解説しているサイトはたくさんあるのですが、一覧でまとめられているものが意外となく、本エントリの価値も少しはあるのではないかと思っています。
字数の都合書ききれなかった部分もありますのでエントリ中に記載したリンク先の詳細を一読するとより正確な演算子の挙動を学ぶことができると思います。