Powershell,Get-Unique吹走已经独特的单一物品

时间:2011-09-13 20:24:17

标签: powershell

我正在从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

2 个答案:

答案 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参数不起作用