iT邦幫忙

2

PowerShell 比較兩個陣列

  • 分享至 

  • xImage
  •  

使用 Compare-Object 比較兩個陣列

預設值:只顯示不同

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> $arr2 = 'A', 'B', 'D'
PS C:\> compare $arr1 $arr2

InputObject SideIndicator
----------- -------------
D           =>
C           <=

列出相同的部份,使用 -IncludeEqual 參數

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> $arr2 = 'A', 'B', 'D'
PS C:\> compare $arr1 $arr2 -IncludeEqual

InputObject SideIndicator
----------- -------------
A           ==
B           ==
D           =>
C           <=

SideIndicator 符號的意思

== 已配對
<= 左邊沒有配對的
=> 右邊沒有配對的

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> $arr2 = 'A', 'B', 'B'
PS C:\> compare $arr1 $arr2 -IncludeEqual

InputObject SideIndicator
----------- -------------
A           ==
B           ==
B           =>
C           <=
$arr2 有兩個B
其中一個已配對,另一個沒有配對

參與比較的東西

可以是 1個物件 or 1個陣列(空陣列也可以)
不可以是 $null

1個陣列 vs 1個物件

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> compare $arr1 'P'

InputObject SideIndicator
----------- -------------
P           =>
A           <=
B           <=
C           <=

1個陣列 vs 空陣列

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> compare $arr1 @()

InputObject SideIndicator
----------- -------------
A           <=
B           <=
C           <=

1個陣列 vs $null

報錯

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> compare $arr1 $null
Compare-Object : 無法將引數繫結到 'DifferenceObject' 參數,因為它是 Null。
位於 線路:1 字元:15
+ compare $arr1 $null
+               ~~~~~

dir命令的可能結果

  • 沒有找到
  • 1個物件
  • 1個陣列(內含多個物件)
# $arr1 可能是 $null
$arr1 = dir *.txt


# $arr1 是一個陣列 (內含 0個物件 or 1個物件 or 多個物件)
$arr1 = @(dir *.txt)

如何比較

比較方式1:以物件本身進行比較

物件不同型別的時候

右邊的物件會`轉型`成左邊的型別,然後進行比較

TimeSpan vs String

PS C:\> compare ([TimeSpan]"0:0:1") "0:0:1" -IncludeEqual

InputObject SideIndicator
----------- -------------
00:00:01    ==

左邊右邊換位置

String vs TimeSpan

PS C:\> compare "0:0:1"  ([TimeSpan]"0:0:1") -IncludeEqual

InputObject SideIndicator
----------- -------------
00:00:01    =>
0:0:1       <=

雖然物件相同型別

PS C:\001> compare @(dir) @(dir) -IncludeEqual

InputObject SideIndicator
----------- -------------
1.txt       ==
A.txt       ==
B.txt       ==
PS C:\001> compare @(dir) @(dir *) -IncludeEqual

InputObject  SideIndicator
-----------  -------------
C:\001\1.txt =>
C:\001\A.txt =>
C:\001\B.txt =>
1.txt        <=
A.txt        <=
B.txt        <=

比較方式2:以物件的屬性進行比較 (使用 -Property 參數)

PS C:\001> compare @(dir) @(dir *) -IncludeEqual -Property Name

Name  SideIndicator
----  -------------
1.txt ==
A.txt ==
B.txt ==

比較多個屬性

2個屬性

PS C:\001> compare @(dir) @(dir *) -IncludeEqual -Property Name, Length

Name  Length SideIndicator
----  ------ -------------
1.txt   4229 ==
A.txt  10538 ==
B.txt  10630 ==

3個屬性

PS C:\001> compare @(dir) @(dir *) -IncludeEqual -Property Name, Length, LastWriteTime

Name  Length LastWriteTime           SideIndicator
----  ------ -------------           -------------
1.txt   4229 2023/8/20 下午 12:16:20 ==
A.txt  10538 2023/8/20 下午 12:16:20 ==
B.txt  10630 2023/8/20 下午 12:16:20 ==

屬性名:不可以用 *

PS C:\001> compare @(dir) @(dir *) -IncludeEqual -Property *
compare : "*" 中不允許有萬用字元。

自訂屬性

script block

PS C:\001> $e = { (Get-FileHash $_ -algo MD5).Hash }
PS C:\001> compare @(dir) @(dir *) -IncludeEqual -Property Name, Length, $e

Name  Length  (Get-FileHash $_ -algo MD5).Hash  SideIndicator
----  ------ ---------------------------------- -------------
1.txt   4229 43D7571729083C00CDD4737312728924   ==
A.txt  10538 3C5F75F757513FDFBC2BEED2846694DF   ==
B.txt  10630 896EBC708B542A54ADECC2C850FBD43C   ==

hash table

PS C:\001> $e = { (Get-FileHash $_ -algo MD5).Hash }
PS C:\001> compare @(dir) @(dir *) -IncludeEqual -Property Name, Length, @{ e = $e }

Name  Length  (Get-FileHash $_ -algo MD5).Hash  SideIndicator
----  ------ ---------------------------------- -------------
1.txt   4229 43D7571729083C00CDD4737312728924   ==
A.txt  10538 3C5F75F757513FDFBC2BEED2846694DF   ==
B.txt  10630 896EBC708B542A54ADECC2C850FBD43C   ==

呈現結果

預設值

只列出沒有配對

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> $arr2 = 'A', 'B', 'D'
PS C:\> compare $arr1 $arr2

InputObject SideIndicator
----------- -------------
D           =>
C           <=

-IncludeEqual 參數

功能:列出已配對
結果:沒有配對已配對

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> $arr2 = 'A', 'B', 'D'
PS C:\> compare $arr1 $arr2 -IncludeEqual

InputObject SideIndicator
----------- -------------
A           ==
B           ==
D           =>
C           <=

-ExcludeDifferent 參數

功能:不列出沒有配對

PowerShell 5 的結果:沒反應

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> $arr2 = 'A', 'B', 'D'
PS C:\> compare $arr1 $arr2 -ExcludeDifferent
PS C:\>

PowerShell 7 的結果:已配對

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> $arr2 = 'A', 'B', 'D'
PS C:\> compare $arr1 $arr2 -ExcludeDifferent

InputObject SideIndicator
----------- -------------
A           ==
B           ==

-ExcludeDifferent -IncludeEqual 同時使用

功能:不列出沒有配對、列出已配對
結果:已配對

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> $arr2 = 'A', 'B', 'D'
PS C:\> compare $arr1 $arr2 -ExcludeDifferent -IncludeEqual

InputObject SideIndicator
----------- -------------
A           ==
B           ==

結果物件

有使用 -PassThru 參數

結果物件的型別:來源物件

PS C:\> compare (dir C:\001) (dir C:\002) -PassThru


    目錄: C:\002


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----       2023/8/20  下午 12:16           3770 2.txt


    目錄: C:\001


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----       2023/8/20  下午 12:16           4229 1.txt

沒使用 -PassThru 參數

結果物件的型別:PSCustomObject

PS C:\> compare (dir C:\001) (dir C:\002)

InputObject SideIndicator
----------- -------------
2.txt       =>
1.txt       <=

來源物件PSCustomObject的共同點

它們都有SideIndicator屬性,可以得知

    <= 
    ==
    =>

當已配對時 (SideIndicator屬性是 ==)

來源物件:只傳回左邊的來源物件

PSCustomObject:InputObject屬性是左邊的來源物件
InputObject屬性的由來:沒有使用 -property 參數,以物件本身進行比較


使用結果物件

結果物件的數量

使用Count屬性

PS C:\> $r = compare 'A' 'A'
PS C:\> $null -eq $r
True
PS C:\> $r.count
0

Count屬性沒反應

PS C:\> $r = compare 'A' 'A' -IncludeEqual
PS C:\> $r.gettype().name
PSCustomObject
PS C:\> $r.count
PS C:\>

把結果放進 @( ) 裡面,使它成為一個陣列
然後使用Count屬性

PS C:\> $r = compare 'A' 'A'
PS C:\> $null -eq $r
True
PS C:\> @($r).count
0
PS C:\> $r = compare 'A' 'A' -IncludeEqual
PS C:\> $r.gettype().name
PSCustomObject
PS C:\> @($r).count
1

SideIndicator屬性選取結果

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> $arr2 = 'A', 'B', 'D'
PS C:\> $r = compare $arr1 $arr2 -IncludeEqual
PS C:\> $r | where SideIndicator -eq '<='

InputObject SideIndicator
----------- -------------
C           <=


PS C:\> $r | where SideIndicator -eq '=='

InputObject SideIndicator
----------- -------------
A           ==
B           ==


PS C:\> $r | where SideIndicator -eq '=>'

InputObject SideIndicator
----------- -------------
D           =>

其他

-SyncWindow 參數

SyncWindow:暫存區的大小。預設值為[Int32]::MaxValue
左邊、右邊各有一個暫存區。

首先,同位置配對

當配對失敗
右邊物件:和左邊暫存區裡的物件配對
左邊物件:和右邊暫存區裡的物件配對

如果成功配對,把成功配對物件從暫存區中移除

如果沒有成功配對,把未配對的物件存到暫存區
如果暫存區滿了,先把最舊的物件取出、設定SideIndicator屬性
再把新的未配對物件,放進暫存區

當比對結束,把暫存區的物件取出,設定SideIndicator屬性

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> $arr2 = 'C', 'B', 'A'
PS C:\> compare $arr1 $arr2 -IncludeEqual

InputObject SideIndicator
----------- -------------
B           ==
A           ==
C           ==

-SyncWindow 0
同位置配對
配對失敗,不保存到暫存區
立刻設定 SideIndicator值

PS C:\> $arr1 = 'A', 'B', 'C'
PS C:\> $arr2 = 'C', 'B', 'A'
PS C:\> compare $arr1 $arr2 -IncludeEqual -SyncWindow 0

InputObject SideIndicator
----------- -------------
C           =>
A           <=
B           ==
A           =>
C           <=

參考資料


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言