Adi Inbar 的有用答案包含有关如何Compare-Object
工作的良好背景信息。
但是,有一种方法可以-Property
通用地比较所有列值- 假设两个输入表具有相同的列结构,或者这些表只能通过第一个表的列进行比较:
# The original collection.
$coll1 = [pscustomobject] @{ one = '1a'; two = '2a'; three = '3a' },
[pscustomobject] @{ one = "1b"; two = "2b"; three = '3b' }
# The other collection to compare the original to.
# Note the difference in the 2nd object in column 'two'
$coll2 = [pscustomobject] @{ one = '1a'; two = '2a'; three = '3a' },
[pscustomobject] @{ one = "1b"; two = "2b!"; three = '3b' }
# PSv3+: Get the array of all property names to compare
# from the original collection.
# Note:
# * The assumption is that both collections have the same set of
# properties (or that the collections should only be compared by
# the *first* collection's properties).
# * In PSv2-, use the following instead:
# $propsToCompare = $coll1[0].psobject.properties | % { $_.name }
$propsToCompare = $coll1[0].psobject.properties.name
# Compare the 2 collections by all property values.
# -PassThru means that any input object in which a difference is found
# is passed through as-is.
Compare-Object $coll1 $coll2 -Property $propsToCompare -PassThru
以上产生:
one two three SideIndicator
--- --- ----- -------------
1b 2b! 3b =>
1b 2b 3b <=
请注意如何=>
告诉您所选对象是右侧独有的,反之亦然<=
需要注意的是,这Compare-Object
很慢,因为它不能对输入数据进行排序假设,因此必须完整地读取和比较两个输入集合。
使用排序输入,您可以-SyncWindow <Int32>
加快速度,但这需要提前了解在发现每个差异后两个输入集合之间最多可以有多少项目不同,如果-SyncWindow
值太小,则会报告虚假差异。
如果将对象作为一个整体进行比较(无-Property
参数),PowerShell 使用以下比较方法:
笔记:
下面,LHS指的是参考集合中的一个对象 ( -ReferenceObject
),而RHS指的是差异集合中的一个对象( -DifferenceObject
)
简而言之:除非所涉及的类型实现IComparable
(对于字符串和所有原始 .NET 类型(CLR 的数字类型和[char]
)都是如此)或具有可以推断相等性的实例特定返回值的自定义实现,否则,.ToString()
整体-对象比较没有意义,即使对象不相等,它们也会被视为相等。
以下逻辑在引擎方法中实现,每当必须比较两个值时都会使用该方法,而与上下文无关。TryCompare()
如果LHS是string,则进行字符串比较,默认不区分大小写和区域性;和参数允许您更改它。-CaseSensitive
-Culture
如果 LHS 和 RHS 都是(可能不同的).NET 基本类型的数字,则执行数字比较。
否则,尝试将 RHS is 转换为 LHS 的类型,如果类型支持,则调用System.IComparable
其方法来确定相等性。.CompareTo()
否则,LHS 和 RHS 通过Object.Equals()
所有对象继承或实现的方法进行比较,或者,如果类型实现 interface IEquatable<T>
,则比较IEquatable<T>.Equals()
。
如果System.Object.Equals()
被调用,并且给定类型没有覆盖它,那么只有struct
仅由其他值类型实例组成的值类型 (s) 才会有意义地进行比较;对于引用类型,只有对同一个对象实例的两个引用被认为是相等的。
警告:从 PowerShell Core 7.1.0-preview.2 开始,仅当.Equals()
调用返回时才true
使用结果。原因是比较代码也用于排序(排序)值,其中仅确定相等性是不够的。在上下文中Compare-Object
,不使用false
结果实际上对于实现(并且不实现)的类型是不合适的- 请参阅此 GitHub 问题。IEquatable<T>
IComparable
剩下的逻辑来自ObjectCommandComparer.Compare()
(也被Get-Unique
and使用Select-Object -Unique
):