2011/05/04

配列変数がnullかそうでないかを調べることはたまにあるかと思います。しかし、

if($array -eq $null)
{
	'$arrayはnull!'
}
else
{
	'$arrayはnullじゃない!'
}

とするのはダメです。たとえば$array=@($null,$null,121,123)というような配列を渡すと「$arrayはnull!」と表示されてしまいます。

なぜこんなことが起きてしまうかというと、-eq演算子は比較演算子であると同時に、配列をフィルタする演算子でもあるからです。たとえば、1,2,2,3,3,3,4,5という要素を持つ配列のうち、2と一致する要素を持つ配列だけを抽出するのはこんな感じです。

PS > $array=@(1,2,2,3,3,3,4,5)
PS > $array -eq 2
2
2

-eq以外にも各種比較演算子が同様に使えます。3以上の要素のみ返すなら$array -ge 3となります。

つまり最初に挙げた例の場合、左辺の$arrayが配列であれば、TrueかFalseを返すのではなく、右辺の値(ここでは$null)と一致するものを抽出して配列として返すのです。よってもし$arrayに複数の$nullが要素として含まれていると、

if($array -eq $null)

if(@($null,$null))

と解釈され、2要素を持つ配列なのでこれは条件文中でTrueに評価されて結果、ifステートメントの中が実行されてしまうわけです。

$nullが一要素しか含まれない配列、すなわち$array=@($null,121,123)のような配列ではまた挙動が変わり、「$arrayはnullじゃない!」と表示されます。これはなぜかというと、

if($array -eq $null)

if(@($null))

と解釈されるためです。@($null)はFalseと解釈されるので、結果elseが実行されるわけです。

$nullを要素に含まない配列$array=@(1,2,3)とかだと問題が起きないのは、$array -eq $nullが長さ0の配列@()を返し、これはFalseと評価されるからです。(これも良く考えると理由がよくわかりませんが)

このように-eq演算子が配列フィルタとして働いてしまうのを防ぎつつ、配列変数が$nullではないかを確認するには次のようにすると良いでしょう

if($null -eq $array)
{
	'$arrayはnull!'
}
else
{
	'$arrayはnullじゃない!'
}

右辺と左辺を入れ替えただけですが、問題なく動きます。

これが気持ち悪いならば

if($array -isnot [array] -and $array -eq $null)

のようにして変数が配列かどうかまず判断するのでもいいかもです。

これ、案外ハマりどころだと思います。「配列要素に二つ以上nullが含まれるときだけ結果がおかしくなる」のも気づきにくい原因。ぜひ気を付けてください。

ちなみに

if($array)
{
    '$arrayはnullじゃない!'
}
else
{
    '$arrayはnull!'
}

なんてのも駄目です。$array=@($false)や$array=@(0)など、要するに、要素数1でその要素がFalseと解釈される配列が来ると「$arrayはnull!」と表示されてしまいます。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2011/05/04/198780.aspx

2010/09/05

PowerShellの-eq演算子を使って文字列の比較をしていたとき、長音記号(ー)と踊り字(ヽ,ヾ,ゝ,ゞ,々)を含む場合に特異な挙動を示したので、参考までに書いておきます。

長音記号と踊り字単独、もしくはこれらの文字から始まる文字列(”ーあああ”など)に関しては、その長音記号と踊り字はすべて同じ文字であるとみなされます。

たとえば

PS> "々" -eq "ー"
True
PS> "ゞあああ" -eq "ヽあああ"
True

-ceq(大文字小文字を区別する-eq)でも同様です。

なお、これらの文字の前に長音記号と踊り字以外の文字がある場合は、別の文字列とみなされます。

PS> "態々" -eq "態ー"
False

これらの文字を含む文字列を比較する場合は十分気を付けてください。たとえば"々"と"ー"は常に別の文字と解釈させたい場合は、

PS> [string]::op_Equality("々","ー")
False

のようにop_Equalityメソッドを使うとよいでしょう。このようにすると.NETのSystem.Stringクラス標準の比較演算を行います。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2010/09/05/192771.aspx


Copyright © 2005-2018 Daisuke Mutaguchi All rights reserved
mailto: mutaguchi at roy.hi-ho.ne.jp
プライバシーポリシー

Books

Twitter