提问人:Kellen Stuart 提问时间:11/30/2017 最后编辑:Kellen Stuart 更新时间:10/16/2019 访问量:15469
PowerShell - 如何判断两个对象是否相同
PowerShell - How to tell if two objects are identical
问:
假设您有两个相同的对象(这意味着它们分别具有相同的属性和相同的值)。
你如何测试平等?
例
$obj1
& $obj2
是相同的
这是我尝试过的:
if($obj1 -eq $obj2)
{
echo 'true'
} else {
echo 'false'
}
# RETURNS "false"
if(Compare-Object -ReferenceObject $obj1 -DifferenceObject $obj2)
{
echo 'true'
} else {
echo 'false'
}
# RETURNS "false"
编辑
这并不相同
答:
2赞
Maximilian Burszley
11/30/2017
#1
我建议用于此任务:Compare-Object
Function Test-Objects
{
Param(
[Parameter(Mandatory,Position=0)]
[PSCustomObject]$Obj1,
[Parameter(Mandatory,Position=1)]
[PSCustomObject]$Obj2
)
[Void](Compare-Object -ReferenceObject $Obj1.PSObject.Properties -DifferenceObject.PSObject.Properties $Obj2 -OutVariable 'Test')
## Tests whether they are equal, no return = success
If (-not $Test)
{
$True
}
Else
{
$False
}
}
PS C:\> $Obj1 = [PSCustomObject]@{
Property1 = 'Value1'
Property2 = 'Value2'
Property3 = 'Value3'
Property4 = 'Value4'
Property5 = 'Value5'
}
PS C:\> $Obj2 = [PSCustomObject]@{
Property1 = 'Value1'
Property2 = 'Value2'
Property3 = 'Value3'
Property4 = 'Value4'
Property5 = 'Value5'
}
PS C:\> Test-Objects $Obj1 $Obj2
True
PS C:\> $Obj2 | Add-Member -MemberType 'NoteProperty' -Name 'Prop6' -Value 'Value6'
PS C:\> Test-Objects $Obj1 $Obj2
False
评论
0赞
Kellen Stuart
11/30/2017
假设你这样做......如果运行上面的代码,它仍然认为等于 ,即使它们不是。我刚刚测试过$obj1 | Add-Member -NotePropertyName 'NewProperty' -NotePropertyValue 'NewValue'
$obj1
$obj2
0赞
Thomas Glaser
11/30/2017
Compare-Object 用于比较 - 这是不可靠的。例如,使用 - 它说它们是平等的。请参见:stackoverflow.com/a/18346380/1244910ToString()
$obj1 = [pscustomobject] @{ 'a' = '5'; 'b' = 7; }; $obj2 = [pscustomobject] @{ 'c' = '6'; 'b' = 7; }
0赞
Maximilian Burszley
12/1/2017
@KolobCanyon 这在事实上是错误的。在我的测试(v2、v5)中,它工作正常。
0赞
Bill_Stewart
12/1/2017
为什么你可以简单地写?if (-not $Test) { $true } else { $false }
-not $Test
0赞
Maximilian Burszley
12/1/2017
@Bill_Stewart我太专注于他的问题示例,但你是绝对正确的
5赞
Bill_Stewart
11/30/2017
#2
您可以通过比较两个对象的属性来比较两个对象的属性和值是否相等。例:PSObject
Compare-Object
Properties
PSObject
if ( -not (Compare-Object $obj1.PSObject.Properties $obj2.PSObject.Properties) ) {
"object properties and values match"
}
else {
"object properties and values do not match"
}
如果要在函数中使用它:
function Test-PSCustomObjectEquality {
param(
[Parameter(Mandatory = $true)]
[PSCustomObject] $firstObject,
[Parameter(Mandatory = $true)]
[PSCustomObject] $secondObject
)
-not (Compare-Object $firstObject.PSObject.Properties $secondObject.PSObject.Properties)
}
-1赞
Kellen Stuart
11/30/2017
#3
我编写了一个函数来检查精确相等:
function Global:Test-IdenticalObjects
{
param(
[Parameter(Mandatory=$true)]$Object1,
[Parameter(Mandatory=$true)]$Object2,
$SecondRun=$false
)
if(-not ($Object1 -is [PsCustomObject] -and $Object2 -is [PsCustomObject))
{
Write-Error "Objects must be PsCustomObjects"
return
}
foreach($property1 in $Object1.PsObject.Properties)
{
$prop1_name = $property1.Name
$prop1_value = $Object1.$prop1_name
$found_property = $false
foreach($property2 in $Object2.PsObject.Properties)
{
$prop2_name = $property2.Name
$prop2_value = $Object2.$prop2_name
if($prop1_name -eq $prop2_name)
{
$found_property = $true
if($prop1_value -ne $prop2_value)
{
return $false
}
}
} # j loop
if(-not $found_property) { return $false }
} # i loop
if($SecondRun)
{
return $true
} else {
Test-IdenticalObjects -Object1 $Object2 -Object2 $Object1 -SecondRun $true
}
} # function
评论
1赞
Bill_Stewart
12/1/2017
1) 不推荐范围 ID。 2) 大量不必要的工作和开销;一个就可以了(见我的答案)。global:
Compare-Object
0赞
Bacon Bits
12/1/2017
#4
这是我使用的功能:
function Test-ObjectEquality {
param(
[Parameter(Mandatory = $true)]
$Object1,
[Parameter(Mandatory = $true)]
$Object2
)
return !(Compare-Object $Object1.PSObject.Properties $Object2.PSObject.Properties)
}
例子:
PS C:\> $obj1 = [pscustomobject] @{ 'a' = '5'; 'b' = 7; };
PS C:\> $obj2 = [pscustomobject] @{ 'a' = '5'; 'b' = 7; };
PS C:\> Test-ObjectEquality $obj1 $obj2
True
PS C:\> $obj2 = [psobject] @{ 'a' = '5'; 'b' = 7; };
PS C:\> Test-ObjectEquality $obj1 $obj2
False
PS C:\> $obj2 = New-Object -TypeName PSObject -Property @{ 'a' = '5'; 'b' = 7; };
PS C:\> Test-ObjectEquality $obj1 $obj2
True
PS C:\> $obj2 = [pscustomobject] @{ 'c' = '6'; 'b' = 7; };
PS C:\> Test-ObjectEquality $obj1 $obj2
False
PS C:\> $obj2 = [pscustomobject] @{ 'a' = '5'; 'b' = 8; };
PS C:\> Test-ObjectEquality $obj1 $obj2
False
PS C:\> $obj2 = [pscustomobject] @{ 'a' = '5'; 'b' = 7; c = 8 };
PS C:\> Test-ObjectEquality $obj1 $obj2
False
PS C:\> $obj2 = [pscustomobject] @{ 'a' = '5'; 'b' = '7'; };
PS C:\> Test-ObjectEquality $obj1 $obj2
False
我当然相信这可能会错过一些东西;但是,如果查看其中的内容,则可以看到对象上每个属性的比较内容:Properties
PS C:\> $obj1.PSObject.Properties | Select-Object -First 1
MemberType : NoteProperty
IsSettable : True
IsGettable : True
Value : 5
TypeNameOfValue : System.String
Name : a
IsInstance : True
我很少关心对象的属性,而不是 、 、 或。MemberType
Name
TypeNameOfValue
Value
另外,请注意,如果您确实需要,您可以比较而不是 .这将比较属性和方法,尽管你只比较方法调用,而不是方法定义。.PSObject.Members
.PSObject.Properties
1赞
KyleMit
9/6/2018
#5
如果要一次测试一个对象属性的相等性,以便比较和对比两个对象并查看哪些单独的部分不同,则可以使用以下函数,该函数改编自本文,了解如何在 Windows PowerShell 中比较两个对象的所有属性
Function Compare-ObjectProperties {
Param(
[PSObject]$leftObj,
[PSObject]$rightObj
)
$leftProps = $leftObj.PSObject.Properties.Name
$rightProps = $rightObj.PSObject.Properties.Name
$allProps = $leftProps + $rightProps | Sort | Select -Unique
$props = @()
foreach ($propName in $allProps) {
# test if has prop
$leftHasProp = $propName -in $leftProps
$rightHasProp = $propName -in $rightProps
# get value from object
$leftVal = $leftObj.$propName
$rightVal = $rightObj.$propName
# create custom output -
$prop = [pscustomobject] @{
Match = $(If ($propName -eq "SamAccountName" ) {"1st"} Else {
$(If ($leftHasProp -and !$rightHasProp ) {"Left"} Else {
$(If ($rightHasProp -and !$leftHasProp ) {"Right"} Else {
$(If ($leftVal -eq $rightVal ) {"Same"} Else {"Diff"})
})
})
})
PropName = $propName
LeftVal = $leftVal
RightVal = $rightVal
}
$props += $prop
}
# sort & format table widths
$props | Sort-Object Match, PropName | Format-Table -Property `
@{ Expression={$_.Match}; Label="Match"; Width=6},
@{ Expression={$_.PropName}; Label="Property Name"; Width=25},
@{ Expression={$_.LeftVal }; Label="Left Value"; Width=40},
@{ Expression={$_.RightVal}; Label="Right Value"; Width=40}
}
然后像这样使用:
$adUser1 = Get-ADUser 'Grace.Hopper' -Properties *
$adUser2 = Get-ADUser 'Katherine.Johnson' -Properties *
Compare-ObjectProperties $adUser1 $adUser2
几个有趣的笔记:
- 如何测试元素是否具有属性
- 如何按名称获取属性值
- 如何创建自定义 PS 对象
- 如何创建嵌套条件/三元运算符
- 如何设置具有固定宽度的表格格式
- 尝试使用 VT 转义序列或
Write-PSObject
对输出进行着色,但无法使其使用优先的固定列宽
上一个:IF 语句中的检查函数说明
评论
Compare-Object -IncludeEqual
$obj1
-IncludeEqual
$true