哈希与PSCustomObject对象内容对比异常问题问询
问题:PowerShell中Compare-Object对比哈希表和PSCustomObject时无法正确识别内容差异
在PowerShell中使用Compare-Object对比整数和数组时,会按内容进行比较,结果符合预期:
PS C:\> $Int1 = 1 PS C:\> $Int2 = 1 PS C:\> $Int3 = 99 PS C:\> $null -eq (Compare-Object -ReferenceObject $Int1 -DifferenceObject $Int2) True PS C:\> $null -eq (Compare-Object -ReferenceObject $Int1 -DifferenceObject $Int3) False PS C:\> $Array1 = @(1, 2, 3) PS C:\> $Array2 = @(1, 2, 3) PS C:\> $Array3 = @(1, 2, 99) PS C:\> $null -eq (Compare-Object -ReferenceObject $Array1 -DifferenceObject $Array2) True PS C:\> $null -eq (Compare-Object -ReferenceObject $Array1 -DifferenceObject $Array3) False
但对比哈希表(Hashtable)和PSCustomObject时,无论内容是否一致,Compare-Object都判定为相同:
PS C:\> $Hash1 = @{a=1;b=2} PS C:\> $Hash2 = @{a=1;b=2} PS C:\> $Hash3 = @{a=1;b=99} PS C:\> $null -eq (Compare-Object -ReferenceObject $Hash1 -DifferenceObject $Hash2) True PS C:\> $null -eq (Compare-Object -ReferenceObject $Hash1 -DifferenceObject $Hash3) True PS C:\> $Obj1 = [PSCustomObject]@{Name = "Sam"; Weight = 145} PS C:\> $Obj2 = [PSCustomObject]@{Name = "Sam"; Weight = 145} PS C:\> $Obj3 = [PSCustomObject]@{Name = "Sam"; Weight = 199} PS C:\> $null -eq (Compare-Object -ReferenceObject $Obj1 -DifferenceObject $Obj2) True PS C:\> $null -eq (Compare-Object -ReferenceObject $Obj1 -DifferenceObject $Obj3) True
为什么会出现这种情况?
Compare-Object默认的比较逻辑依赖于对象的默认相等性判断或字符串表示:
- 对于整数、数组这类简单类型,PowerShell会直接比较它们的内容值,所以结果符合预期。
- 对于哈希表(
Hashtable),它的默认ToString()输出始终是System.Collections.Hashtable,和内容无关;同时哈希表没有重写相等性比较逻辑,Compare-Object无法识别内部键值对的差异。 - 对于
PSCustomObject,默认情况下Compare-Object不会自动遍历比较其属性内容,而是将整个对象作为一个整体进行引用或字符串比较,因此无法识别属性值的变化。
如何正确对比这类对象的内容?
1. 对比哈希表内容
方法一:序列化为JSON字符串比较
将哈希表转换为JSON格式字符串,利用JSON序列化会保留内容的特性进行对比:
# 对比内容相同的哈希表 $null -eq (Compare-Object (ConvertTo-Json $Hash1) (ConvertTo-Json $Hash2)) # 返回 True # 对比内容不同的哈希表 $null -eq (Compare-Object (ConvertTo-Json $Hash1) (ConvertTo-Json $Hash3)) # 返回 False
方法二:提取键值对排序后比较
将哈希表的键值对提取为有序的字符串数组,再进行对比:
$hash1Kv = $Hash1.GetEnumerator() | Sort-Object Name | ForEach-Object {"$($_.Name)=$($_.Value)"} $hash3Kv = $Hash3.GetEnumerator() | Sort-Object Name | ForEach-Object {"$($_.Name)=$($_.Value)"} $null -eq (Compare-Object $hash1Kv $hash3Kv) # 返回 False
2. 对比PSCustomObject内容
方法一:指定要比较的属性
使用Compare-Object的-Property参数,明确指定需要对比的对象属性:
# 对比内容相同的对象 $null -eq (Compare-Object $Obj1 $Obj2 -Property Name, Weight) # 返回 True # 对比内容不同的对象 $null -eq (Compare-Object $Obj1 $Obj3 -Property Name, Weight) # 返回 False
方法二:序列化为JSON字符串比较
同样可以用JSON序列化的方式,自动遍历所有属性进行对比:
$null -eq (Compare-Object (ConvertTo-Json $Obj1) (ConvertTo-Json $Obj3)) # 返回 False
内容的提问来源于stack exchange,提问作者lit
相关产品推荐
相关产品推荐

