しばたテックブログ

PowerShellを中心に気分で書いている技術ブログです。

PowerShellの比較演算子についてあれやこれや

PowerShellの基本的なことがわかってなかったシリーズ第四弾です。
比較演算子についてあれやこれやと書いていきます。
とはいえ半分くらいは愚痴かも...

基本的には-eq演算子について触れますが他の演算子も大体同様なはず。

1.文字列の比較がデフォルトでIgnore Caseである

ずっと思い込みで文字列の比較はCase Sensitiveだと思っていました。
でも実際には、

PS C:\> "abc" -eq "aBc"
True

な感じでIgnore Caseです。
Case Sensitiveに比較をする場合は-ceq演算子を使う必要があります。
また、-ieqとIgrore Caseを明示した演算子もあります。

PS C:\> "abc" -ceq "aBc"
False

PS C:\> "abc" -ieq "aBc"
True

ちなみに-ne-ge-gt-le-lt-like-notlike-match-notmatch-contains-notcontains-replace-split演算子も同様です。

個人的にはこの仕様には納得がいっていません。
例えば"abc".Equals("aBc")な風に普通にEqualsメソッドが使えるシェルで、当然この結果はCase SensitiveなのでFalseを返すのにもかかわらず-eq演算子はIgnore Caseってのは.NETの世界観にそぐわない気がして仕方がないのです。
とはいえ、実際にこういう仕様になってしまっているので割り切るしかないのですが...

文字列比較のより詳しい話はぎたぱそさんのこちらのエントリを見ていただくほうが良いかと思います。

tech.guitarrapc.com

2.左辺値の型に変換されて比較される

これは仕方ない仕様だとは思います。
比較する左辺と右辺の型が違う場合、右辺値の型を左辺に合わせる様に変換を試みてから比較を行うというものです。
極端な例を出すと、

PS C:\> 0 -eq ""
True

なんてことが起きます。
これは実際には以下の様な変換が行われて比較されます。

PS C:\> 0 -eq [int]""

[int]""0に変換されるため、0 -eq [int]""0 -eq 0となりTrueが返されることになります。

ちなみに逆の場合は、

PS C:\> "" -eq 0
  ↓
PS C:\> "" -eq [string]0
  ↓
PS C:\> "" -eq "0"
False

となります。

3.比較演算子がFilterとして作用する場合がある

左辺値に配列が来た場合に比較演算子がFilterとして機能します。

以下に例を挙げると、

PS C:\> @("a", "b", "c") -eq "A"
a

Falseを返さずフィルタされた結果の"a"が返されます。

牟田口さんのこちらのエントリにもありますが、配列のNULLチェックを行う際はこの仕様に注意する必要があります。

winscript.jp

しかし...これは本当にどうしてこうなった!?としか思えないんですがどうなんですかね?
比較は比較、フィルタはフィルタで個別に演算子を分けるべきだったんじゃないのかと思うんですけど一体何があったんでしょうか...