余り本件に関して書くことが無いのですが…一応簡単なサンプルを。 今回は、時々アレっ?って自分で思うため、テキストに含まれるかどうか/比較を見る方法のメモです。 ====
サンプル
今回、これらを試してみます。
"abc".Contains("a") "Abc".Contains("a") "" "abc" -contains "a" @("abc","bc","c") -contains "a" @("abc","bc","c") -contains "c" @("abc","bc","C") -contains "c" "" "abc" -ccontains "a" @("abc","bc","c") -ccontains "a" @("abc","bc","c") -ccontains "c" @("abc","bc","C") -ccontains "c" "" "a" -in "abc" "a" -in @("abc","bc","c") "c" -in @("abc","bc","c") "c" -in @("abc","bc","C") "" "a" -cin "abc" "a" -cin @("abc","bc","c") "c" -cin @("abc","bc","c") "c" -cin @("abc","bc","C") "" "abc" -match "a" "abc" -match "A" "abc" -cmatch "a" "abc" -cmatch "A" "" [regex]::Match("abc","a") "" "abc" -eq "a" "a" -eq "a" "A" -eq "a" "" "abc" -ceq "a" "a" -ceq "a" "A" -ceq "a" "" "abc".Equals("a") "a".Equals("a") "a".Equals("A") "" 'ー'.Contains('々') 'ー' -contains '々' 'ー' -ccontains '々' '々' -in 'ー' '々' -cin 'ー' 'ー' -match '々' 'ー' -cmatch '々' 'ー' -eq '々' 'ー' -ceq '々' 'ー'.Equals('々') [Object]::ReferenceEquals('ー', '々')
結果を見てみましょう。
True #"abc".Contains("a") False #"Abc".Contains("a") False #"abc" -contains "a" False #@("abc","bc","c") -contains "a" True #@("abc","bc","c") -contains "c" True #@("abc","bc","C") -contains "c" False #"abc" -ccontains "a" False #@("abc","bc","c") -ccontains "a" True #@("abc","bc","c") -ccontains "c" False #@("abc","bc","C") -ccontains "c" False #"a" -in "abc" False #"a" -in @("abc","bc","c") True #"c" -in @("abc","bc","c") True #"c" -in @("abc","bc","C") False #"a" -cin "abc" False #"a" -cin @("abc","bc","c") True #"c" -cin @("abc","bc","c") False #"c" -cin @("abc","bc","C") True #"abc" -match "a" True #"abc" -match "A" True #"abc" -cmatch "a" False #"Abc" -cmatch "A" #[regex]::Match("abc","a") Groups : {a} Success : True Captures : {a} Index : 0 Length : 1 Value : a False #"abc" -eq "a" True #"a" -eq "a" True #"A" -eq "a" False #"abc" -ceq "a" True #"a" -ceq "a" False #"A" -ceq "a" False #"abc".Equals("a") True #"a".Equals("a") False #"a".Equals("A") False #'ー'.Contains('々') True #'ー' -contains '々' True #'ー' -ccontains '々' True #'々' -in 'ー' True #'々' -cin 'ー' False #'ー' -match '々' False #'ー' -cmatch '々' True #'ー' -eq '々' True #'ー' -ceq '々' False #'ー'.Equals('々') False #[Object]::ReferenceEquals('ー', '々')
それぞれ見てみます。
contains()
このようなコードでした。
"abc".Contains("a") "Abc".Contains("a") 'ー'.Contains('々')
結果はこうですね
True #"abc".Contains("a") False #"Abc".Contains("a") False #'ー'.Contains('々')
動作は、そのままです。 "Value".Contrains(x) の時、Valueにxが含まれるかをCase Sensitiveに判定します。
-contains
このようなコードでした。
"abc" -contains "a" @("abc","bc","c") -contains "a" @("abc","bc","c") -contains "c" @("abc","bc","C") -contains "c" 'ー' -contains '々'
結果はこうですね
False #"abc" -contains "a" False #@("abc","bc","c") -contains "a" True #@("abc","bc","c") -contains "c" True #@("abc","bc","C") -contains "c" True #'ー' -contains '々'
.Contains()と異なるのが分かります。 @("Value1","Value2","Value3") -Contrains "x" の時、xが配列の要素"Value1"と"Value2"に含まれるかを判定します。 この判定は、配列要素との判定であり、配列の構成文字ではありません。 つまり、Value1="abc"とx="a"の場合場合は「"abc"に"a"が含まれるかどうかの判定ではありません」。 .Contains()が、"abc"と"a"の場合は「"abc"に含まれるかどうか判定」であるため、.Contains()と-containsでは動作が違います。 時々アレ?っと思っちゃいます。
-ccontains
このようなコードでした。
"abc" -ccontains "a" @("abc","bc","c") -ccontains "a" @("abc","bc","c") -ccontains "c" @("abc","bc","C") -ccontains "c" 'ー' -ccontains '々'
結果はこうですね
False #"abc" -ccontains "a" False #@("abc","bc","c") -ccontains "a" True #@("abc","bc","c") -ccontains "c" False #@("abc","bc","C") -ccontains "c" True #'ー' -ccontains '々'
-containsは、Case Sensitiveに判定しませんでした。 Case Sencitiveに判定するには、-ccontainsとします。
-in
このようなコードでした。
"a" -in "abc" "a" -in @("abc","bc","c") "c" -in @("abc","bc","c") "c" -in @("abc","bc","C") '々' -in 'ー'
結果はこうですね
False #"a" -in "abc" False #"a" -in @("abc","bc","c") True #"c" -in @("abc","bc","c") True #"c" -in @("abc","bc","C") True #'々' -in 'ー' False #[Object]::ReferenceEquals('ー', '々')
-inは、PowerShell 3.0から追加されました。 動作は、-containsのOperatorが逆になったものです。 "x" -in @("Value1","Value2","Value3") の時、xが配列の要素"Value1"と"Value2"に含まれるかを判定します。 -containsに比べて、右辺と左辺が入れ替わっていることが分かります。
-cin
このようなコードでした。
"a" -cin "abc" "a" -cin @("abc","bc","c") "c" -cin @("abc","bc","c") "c" -cin @("abc","bc","C") '々' -cin 'ー'
結果はこうですね
False #"a" -cin "abc" False #"a" -cin @("abc","bc","c") True #"c" -cin @("abc","bc","c") False #"c" -cin @("abc","bc","C") True #'々' -cin 'ー'
-inは、Case Sensitiveに判定しませんでした。 Case Sencitiveに判定するには、-cinとします。
-match
このようなコードでした。
"abc" -match "a" "abc" -match "A" 'ー' -match '々'
結果はこうですね
True #"abc" -match "a" True #"Abc" -cmatch "a" False #'ー' -match '々'
動作は、そのままです。 "Value" -match "x" の時、正規表現でValueにxが含まれるかを判定します。
-cmatch
このようなコードでした。
"abc" -cmatch "a" "abc" -cmatch "A" 'ー' -cmatch '々'
結果はこうですね
True #"abc" -cmatch "a" False #"abc" -cmatch "A" False #'ー' -cmatch '々'
-matchは、Case Sensitiveに判定しませんでした。 Case Sencitiveに判定するには、-cmatchとします。
[regex]::Match()
このようなコードでした。
[regex]::Match("abc","a")
結果はこうですね
#[regex]::Match("abc","a") Groups : {a} Success : True Captures : {a} Index : 0 Length : 1 Value : a
動作は、そのままです。 [regex]::Match("Value","x")の時、正規表現でValueにxが含まれるかをCase Sensitive判定します。
-eq
このようなコードでした。
"abc" -eq "a" "a" -eq "a" "A" -eq "a" 'ー' -eq '々'
結果はこうですね
False #"abc" -eq "a" True #"a" -eq "a" True #"A" -eq "a" True #'ー' -eq '々'
動作は、そのままと思いきや、'ー' と '々' がTrue? ここはトラップになりそうな…。 さて、少し見てみましょう。 ここによると、基本的には、参照比較ではなく値比較のようですが、SecureStringのように参照比較しかクラスにない場合は、参照比較を行うようです。
PowerShell’s -EQ Operator: Reference Equality vs Value Equality
そしてここで詳しく解説されています。
PowerShell equality operator not a symmetric relation?
この理解が必要なようです。
-eq in PowerShell is not an equivalence relation.
動的型付け、というのがポイントといえるようです。(PowerShellは、左オペラントの型に右オペラントをキャストしようとします) ……しかし、 'ー' と '々' がTrueなのは……んー。 booleanにも癖があるようです。 これはどうなるでしょうか。
[ConsoleColor]::Black -eq $true $true -eq [ConsoleColor]::Black
結果です。
False True
順序を入れかえると結果が変わりました。 $nullに対しても、同様の癖があるようです。 配列時の-eqのフィルタ挙動と、$nullが含まれる際の動作については、牟田口先生の解説が参考になります。
if($array -eq $null) には要注意!
$nullに関しては、「分からない」を示すものと考えればよさそうですね。 これについては、SQLの記事ですがbleis先生が参考になります。
ぐるぐる~ - SQLアンチパターン
一応、現在の理解は以下です。
Value -eq x の時に、Value と x を比較する。 基本的には値比較だが、参照比較になりうる。 特に、PowerShellは左オペランドの型に左右されるため注意。 また、boolean/null判定する場合は、$true -eq Value あるいは $null -eq Valueのように順序に気を付ける。 配列で利用した場合にフィルタ動作を行う。
-ceq
このようなコードでした。
"abc" -ceq "a" "a" -ceq "a" "A" -ceq "a" 'ー' -ceq '々'
結果はこうですね
False #"abc" -ceq "a" True #"a" -ceq "a" False #"A" -ceq "a" 'ー' -ceq '々'
-eqは、Case Sensitiveに判定しませんでした。 Case Sencitiveに判定するには、-ceqとします。
.Equals()
このようなコードでした。
"abc".Equals("a") "a".Equals("a") "a".Equals("A") 'ー'.Equals('々')
結果はこうですね
False #"abc".Equals("a") True #"a".Equals("a") False #"a".Equals("A") False #'ー'.Equals('々')
動作は、そのままですね。あー、良かった。 "Value".Equals(x) の時、Valueとxが一致するかをCase Sensitiveに判定します。
[Object]::ReferenceEquals()
このようなコードでした。
[Object]::ReferenceEquals('ー', '々')
結果はこうですね
False #[Object]::ReferenceEquals('ー', '々')
動作は、そのままですね。 [Object]::ReferenceEquals(Value, x)の時、Valueとxの参照先が一致するかを判定します。
まとめ
単純に文字列を比較するなら…この辺が適してそうですね。
.Contains() .Equals() -match [regex]::Match()
オブジェクトの比較時には -eq を頻繁に利用しますが、少し注意をした方がいいようです。
参考
Windows PowerShell Version 3 Simplified Syntax Does -eq keyword in power shell test reference equality or use Object.Equals() Part-5: Text Manipulation in PowerShell using .Contains() and .Equals() methods