我正在从xml文件中收集信息并进行处理。我的查询很自由,以确保我获得所有可能的元素。因此,最终可能会在结果列表中使用重复元素(称为$components
)。我通过Sort-Object
然后Get-Unique
运行结果以查找所有唯一对象。据我了解,每个唯一对象之一应由Get-Unique
保留。但它消除了一些已经很独特的对象(原始列表中没有重复的对象)。
这是一个简化的例子。只需将其粘贴到PowerShell中或保存到ps1文件并运行(输出如下所示):
$xmlDoc = [xml]@'
<root>
<component Id='component1'>
<regkey Id='regkey1'/>
</component>
<component Id='component2'>
<file Id='file1' />
</component>
</root>
'@
$files = $xmlDoc.SelectNodes("//file[@Id='file1']")
$regkeys = $xmlDoc.SelectNodes("//regkey[@Id='regkey1']")
$components = $xmlDoc.SelectNodes("//component[@Id='component1'] | //component[@Id='component2']")
$components += $regkeys | Select-Object -ExpandProperty 'ParentNode'
$components | Sort-Object -Property 'Id'
Write-Host
$components | Sort-Object -Property 'Id' | Get-Unique
如果您粘贴到PowerShell中,请在最后一行后按Enter键。
输出如下:
PS C:\> $xmlDoc = [xml]@'
>> <root>
>> <component Id='component1'>
>> <regkey Id='regkey1'/>
>> </component>
>> <component Id='component2'>
>> <file Id='file1' />
>> </component>
>> </root>
>> '@
>>
PS C:\> $files = $xmlDoc.SelectNodes("//file[@Id='file1']")
PS C:\> $regkeys = $xmlDoc.SelectNodes("//regkey[@Id='regkey1']")
PS C:\> $components = $xmlDoc.SelectNodes("//component[@Id='component1'] | //component[@Id='component2
']")
PS C:\> $components += $regkeys | Select-Object -ExpandProperty 'ParentNode'
PS C:\> $components | Sort-Object -Property 'Id'
Id regkey
-- ------
component1 regkey
component1 regkey
component2
PS C:\> Write-Host
PS C:\> $components | Sort-Object -Property 'Id' | Get-Unique
Id regkey
-- ------
component1 regkey
PS C:\>
注意component2
在我们输入Get-Unique
后完全消失的方式。任何人都可以解释这个并提供一个修复程序,使查询方案保持不变吗?
编辑:我假设它会使用-eq
运算符来查看元素是否是对内存中同一对象的引用。如果我手动尝试-eq
,它会显示正确的对象相等。但Get-Unique似乎在做其他事情。如果将此代码添加到上述脚本的末尾,则显示对象等效:
Write-Host
Write-Host "0: $($components[0].Id)"
Write-Host "1: $($components[1].Id)"
Write-Host "2: $($components[2].Id)"
Write-Host ("0 vs 1: " + ($components[0] -eq $components[1]))
Write-Host ("0 vs 2: " + ($components[0] -eq $components[2]))
Write-Host ("1 vs 2: " + ($components[1] -eq $components[2]))
输出(从脚本文件运行时):
0: component1
1: component2
2: component1
0 vs 1: False
0 vs 2: True
1 vs 2: False
答案 0 :(得分:5)
您可以使用-unique
的{{1}}标记。这给了我预期的结果:
sort-object
答案 1 :(得分:2)
我的直觉是Get-Unique
适用于标量类型,如整数,字符串等(也许是一组众所周知的类型),而不适用于一般对象,因为没有一般规则可以决定对象是否相等。
考虑这个例子:
# getting unique string, works well
get-process | sort-object | select -expand processname | get-unique
# getting unique objects (PSObject), wrong result
get-process | sort-object | select -property processname | get-unique
# getting unique objects by their string representation, works well
get-process | sort-object | select -property processname | get-unique -asString
# what is the string representation?
[string](get-process | sort-object | select -property processname)[0]
#returns @{ProcessName=audiodg}
在您的情况下,字符串表示为:
[string]($components | Sort-Object -Property 'Id')[0]
# System.Xml.XmlElement
这就是为什么偶数-asString
参数不起作用