2011-09-13 8 views
3

xmlファイルから情報を収集して処理しています。私が望むすべての要素を確実に得るために、私の質問はリベラルです。その結果、結果リスト($componentsと呼ばれます)に重複する要素で終わる可能性があります。私は結果をSort-Objectまで実行し、次にGet-Uniqueを実行してすべての一意のオブジェクトを見つけました。ユニークなオブジェクトの1つはGet-Uniqueのままにしておきます。しかし、すでに一意のオブジェクト(元のリストに重複していないオブジェクト)の一部が削除されています。Powershell、Get-Unique既に一意の単一オブジェクトを吹き飛ばす

ここでは簡単な例を示します。ただ、PowerShellのにこれを貼り付けたり、PS1ファイルと実行(下に示す出力)に保存する:あなたはPowerShellのに貼り付けた場合は、その最後の行の後にEnterキーを押し

$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 

出力は次のようなものです:component2は完全に一度、私たちにパイプGet-Uniqueに消えるか

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:\> 

注意してください。誰もがこれを説明し、同一のクエリスキームを保持する修正を提供できますか?

編集-eq演算子を使用して、要素がメモリ内の同じオブジェクトへの参照であるかどうかを確認すると仮定しました。手動で-eqを試してみると、正しいオブジェクトが等しいことがわかります。しかしGet-Uniqueは何か他のことをしているようです。あなたは上記のスクリプトの最後にこのコードを追加した場合には、オブジェクトのequivelanceを示しています

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

'-asstring'パラメータを試してください。 Get-Uniqueのテクニカル記事から - **このパラメータがなければ、データはオブジェクトとして扱われるため、同じタイプのオブジェクトのコレクションをGet-Uniqueに提出すると、ファイルのコレクションなど、1つだけが返されます(最初)** – JNK

+0

私は運が無かった。 :/ – Vimes

+0

私は、重複したオブジェクトが実際にメモリ内の同じオブジェクトへの2つの参照であり、比較がデフォルトで正しいと予想していると考えました。明らかに、より多くのことが起こっている。 – Vimes

答えて

2

私の直感では、そのGet-Unique作品もありますオブジェクトが等しいかどうかを決定する一般的な規則がないため、int、文字列などのスカラー型(および多分よく知られた型の集合のため)であり、一般的なオブジェクトではない。あなたのケースの文字列表現で

# 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} 

です:でも-asStringパラメータはあなたがsort-object-uniqueフラグを使用することができます

5

動作しない理由です

[string]($components | Sort-Object -Property 'Id')[0] 
# System.Xml.XmlElement 

は、この例で考えてみましょう。それは私にとって期待される結果をもたらします:

$components | Sort-Object -Property 'Id' -Unique 
+0

これは上記の例ではうまくいくようですが、実際のコードを試してみると、反対の問題が発生します.2つのコピーが消えてしまい、元のリストで一意のオブジェクトが1つだけ残ってしまいます。私は困惑している。残念ながら私は実際のデータを掲載することはできません(それは仕事用です)。私は実際のデータと上記の例とで何が違うのかを把握する時間はないと思う。 – Vimes

+0

おっと、これ以上の私のコメントでは、私は反対の問題を抱えていません。私はまったく同じ問題を抱えています。 :P私のオブジェクトを混ぜる。 – Vimes

関連する問題