use*_*851 7 powershell powershell-2.0
我有两个Excel电子表格我想比较:
$OleDbAdapter = New-Object System.Data.OleDb.OleDbDataAdapter “Select * from [Report$]“,”Provider=Microsoft.ACE.OLEDB.12.0;Data Source=S:\FIS-BIC Reporting\Report Output Files\Product-Marketing\TEST_XI\ECM - Pipeline by LOB_04182013_040544.xls;Extended Properties=”"Excel 12.0 Xml;HDR=YES”";”
$RowsReturned = $OleDbAdapter.Fill($DataTable)
$OleDbAdapter2 = New-Object System.Data.OleDb.OleDbDataAdapter “Select * from [Report$]“,”Provider=Microsoft.ACE.OLEDB.12.0;Data Source=S:\FIS-BIC Reporting\Report Output Files\Product-Marketing\ECM - Pipeline by LOB_04182013_074004.xls;Extended Properties=”"Excel 12.0 Xml;HDR=YES”";”
$RowsReturned2 = $OleDbAdapter2.Fill($DataTable2)
Compare-Object $DataTable $DataTable2 
它什么都不返回.我知道在第6栏中,它们是不同的.如果我指定"-property F6",它确实会返回差异.除非我指定属性,否则任何想法都没有?列数可以变化(虽然比较中的每个文件都相同),因此具体指定属性将不起作用.
Adi*_*bar 23
如果未指定-Property参数,则Compare-Object不会比较所有属性,而是比较在两个对象上调用.ToString()方法的结果.因此,Compare-Object $DataTable $DataTable2将$ DataTable1.ToString()与$ DataTable1.ToString()进行比较.在DataTable对象上调用时,.ToString()方法返回一个空字符串,因此报告没有区别.
例如:
$file1 = Get-Item somefilename
$file1 = Get-Item anotherfilename
Compare-Object $file1 $file2
这将返回两个文件的完整路径之间的差异,如下所示:
InputObject              SideIndicator
-----------              -------------
<path>\anotherfilename   =>
<path>\somefilename      <=
这是因为在FileInfo对象上调用.ToString()会返回其FullName属性,因此您要比较文件的完整路径名.
虽然-Property参数接受多个属性,但列出所有属性不是解决方案.除了非常乏味,它不会给你你想要的结果.如果列出多个属性,则Compare-Object会比较所有属性的组合,如果列出的属性中的任何一个不同,则返回显示所有列出属性的结果(两个属性相同且不同的属性)作为单一的差异.
您需要做的是迭代属性列表,并为每个属性调用一次Compare-Object:
$properties = ($DataTable | Get-Member -MemberType Property | Select-Object -ExpandProperty Name)
foreach ($property in $properties) {
  Compare-Object $DataTable $DataTable2 -Property "$property" | Format-Table -AutoSize
}
在大多数情况下,在比较两个对象的所有属性时,您需要使用Get-Member -MemberType Properties,以覆盖所有属性类型.但是,如果您要比较DataTable对象,最好使用它,Get-Member -MemberType Property以便仅比较与数据字段对应的属性,而不是与数据无关的DataTable对象的其他属性.
这是写入假设列数是一样的,如你所说,或者至少在列数$ DataTable2不超过列数$ DataTable中.
如果你不能可靠地假设,推导出$属性阵列由哪一个有更多的列,通过比较($DataTable | Get-Member -MemberType Property).Count与($DataTable2 | Get-Member -MemberType Property).Count和使用性质从以较高者为准.
使用Format-Table非常重要,它不仅仅是让事物变得漂亮.如果列出多个相同类型的对象(在本例中为数组),PowerShell会记住第一个对象的格式,并将其用于所有后续对象,除非您明确指定格式.由于第一列的名称对于每个属性(即电子表格中的每一列)都不同,因此除了遇到的第一个差异外,第一列将为空.
该-AutoSize开关是可选的.那就是让事情看起来很漂亮.但是您必须将结果传递给格式化过滤器.如果您愿意,也可以使用Format-List.
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
上面的结果是:
# 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
请注意如何=>告诉您所选对象是右侧独有的,反之亦然<=
需要注意的是,速度Compare-Object很慢,因为它无法对输入数据进行排序做出假设,因此必须完整读取和比较两个输入集合。
通过排序输入,您可以用来-SyncWindow <Int32>加快速度,但这需要预先了解在发现每个差异后两个输入集合之间最多有-SyncWindow多少个项目可以不同,如果该值太小,则会报告虚假差异。
如果将对象作为一个整体进行比较(无-Property参数),PowerShell 使用以下比较方法:
笔记:
下面,LHS引用参考集合 ( -ReferenceObject) 中的对象,RHS引用差异集合 ( -DifferenceObject)中的对象
它的缺点是:除非涉及的类型实现IComparable[char](对于字符串和所有原始 .NET 类型(CLR 的数字类型和)来说都是如此)或具有具有特定于实例的返回值(可以从中推断出相等性)的自定义实现,否则,.ToString()整个 -对象比较没有意义,即使对象不相等,它们也会被视为相等。
以下逻辑在引擎方法中实现,每当必须比较两个值时就会使用该逻辑,而不管上下文如何。TryCompare() 
如果 LHS 是string,则进行字符串比较,默认不区分大小写且文化不变;和-CaseSensitive参数-Culture允许您更改它。
如果 LHS 和 RHS 都是(可能不同的).NET 基元类型的数字,则执行数字比较。
否则,尝试将 RHS is 转换为 LHS 的类型,如果该类型支持System.IComparable,.CompareTo()则调用其方法来确定相等性。
否则,LHS 和 RHS 通过Object.Equals()所有对象继承或实现的方法进行比较,或者,如果该类型实现接口IEquatable<T>,IEquatable<T>.Equals()。
如果System.Object.Equals()被调用,并且给定类型不会覆盖它,则只有struct仅由其他值类型实例组成的值类型才会有意义地进行比较;对于引用类型,只有对同一对象实例的两个引用才被视为相等。
警告:从 PowerShell Core 7.1.0-preview.2 开始,仅当.Equals()调用返回true时才使用结果。原因是比较代码还用于对值进行排序(排序),仅确定相等性是不够的。在上下文中Compare-Object,不使用false结果实际上对于实现(以及不实现)的类型是不合适的- 请参阅此 GitHub 问题。IEquatable<T>IComparable
剩下的逻辑来自ObjectCommandComparer.Compare()(也被Get-Uniqueand使用Select-Object -Unique):
如果上述方法均不适用,则根据对象的.ToString()表示形式对对象进行比较(具有与上述相同的字符串比较细节)。
.ToString()实现只是返回完整的类型名称(例如,'System.IO.FileInfo'),以便该类型的所有实例比较相同的。| 归档时间: | 
 | 
| 查看次数: | 15122 次 | 
| 最近记录: |