查找array1中但不在array2中的项目

时间:2014-08-11 13:32:05

标签: arrays powershell foreach

我从两个不同的工具Array1Array2中提取了两个计算机列表。

现在我需要提取Array1中但不在Array2中的内容。

我设法通过这样做获得所有匹配的:

$matchingComp = @()

foreach ($SCCMcomputer in $SCCMcomputers) {
    foreach ($eWPTcomputer in $eWPTcomputers) {
        if ($SCCMcomputer.Computername -eq $eWPTComputer.Computername) {
            $obj = New-Object PSObject
            $obj | Add-Member -MemberType NoteProperty -Name "ComputerName" -Value $SCCMcomputer.Computername
            $matchingComp +=$obj
        }
    }
}

$matchingComp | Export-Csv $inEWPT -Delimiter "," -NoTypeInformation

但我仍然需要$SCCMcomputer但不在$eWPTcomputers中的那些......

我在其他语言(例如Perl)上找到了SO的解决方案,但没有找到适用于PowerShell的解决方案。

更新

我仍然无法使用以下公式在Excel中获得正确的输出:

enter image description here

输出如下:

enter image description here

意味着有些人在这里,有些则没有。 powershell中的输出就像这样

enter image description here

表示0KB是emtpy。

$SCCMcomputers | Export-Csv $sccmexport -Delimiter "," -NoTypeInformation
$eWPTcomputers | Export-Csv $ewptexport -Delimiter "," -NoTypeInformation
Compare-Object -ReferenceObject $SCCMcomputers -DifferenceObject $eWPTcomputers | ?{$_.sideIndicator -eq "=>"} |select inputobject | Export-Csv $inEWPT -NoTypeInformation
Compare-Object -ReferenceObject $SCCMcomputers -DifferenceObject $eWPTcomputers | ?{$_.sideIndicator -eq "=="} |select inputobject | Export-Csv $inBoth -NoTypeInformation
Compare-Object -ReferenceObject $SCCMcomputers -DifferenceObject $eWPTcomputers | ?{$_.sideIndicator -eq "<="} |select inputobject | Export-Csv $inSCCM -NoTypeInformation

来自SCCMcomptuers / eWPTcomputers的列名(或其名称)是&#34; Computername&#34;

知道我可能做错了吗?两个计算机阵列都是从SQL和哈希表(我认为它被称为)生成的:@{Computername=......}@{Computername....,就像这样。

更新2

foreach ($t in $sccmComputers) {
    $Test1 += $t.computername
}

$Test2 = @()
foreach ($t in $ewptComputers) {
    $Test2 += $t.computername
}

删除Hashtable的Header,只是让数组充满了字符串,幻想着......甚至-Property computername都没有用......:S

5 个答案:

答案 0 :(得分:11)

使用compare-object cmdlet

Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt | ?{$_.sideIndicator -eq "<="} |select inputobject

示例:

$sccm=@(1,2,3)   
$wpt=@(2,4)

Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt -IncludeEqual   

将输出:

  

InputObject SideIndicator

     
      2 ==            
      4 =>            
      1 <=            
      3 <=

这意味着价值&#34; 2&#34;在两个对象上,&#34; 1&#34;和&#34; 3&#34;仅在&#34;左侧&#34; (即参考对象),而&#34; 4&#34;只是在差异对象

答案 1 :(得分:2)

使用compare-object如下

Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt -passthru

这应该只给你$ sccm中的对象,而不是$ wpt。

<强> CORRECTION:

以上代码适用于保证DifferenceObject是ReferenceObject的子集的情况。但是,如果DifferenceObject中还有其他对象存在于ReferenceObject中,则它将失败。上面的代码返回EITHER ReferenceObject或DifferenceObject中存在但在两者中都不存在的任何对象。

要正确返回ReferenceObject中仅在DifferenceObject中不存在的对象,需要以下代码:

Compare-Object -ReferenceObject $sccm  -DifferenceObject $wpt | 
    Where-Object { $_.SideIndicator -eq '<=' } | 
    ForEach-Object  { Write-Output $_.InputObject }

where-object子句确保只有ReferenceObject中存在的对象才会传递给管道。

foreach-object子句强制输出回一个简单的数组(参考:Converting Custom Object arrays to String arrays in Powershell - 谢谢Keith)

答案 2 :(得分:1)

您可以使用-contains-notcontains

$A1 ="asd","zxc","qwe",'a'
$A2 = "asd","zxc","bqwe",'b'
$A1,$A2 | 
%{
    $_| 
        %{
        If ($A1 -contains $_ -and $A2 -notcontains $_) {$_}
        }
}

答案 3 :(得分:1)

Compare-Object方法确实是最好的。还没有解决的问题是Excel文件的清晰输出。

Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '<=' | Export-Csv sccm-only.csv -NoTypeInformation

将生成两列。一个用&#34; InputObject&#34;和你的计算机名称,另一栏用&#34; SideIndicator&#34;和一堆行&#34;&lt; =&#34;。

简单的解决方法是只选择您想要的列:

Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '<=' | Select-Object InputObject | Export-Csv sccm-only.csv -NoTypeInformation

这将为您提供一个标有&#34; InputObject&#34;的列。和你的电脑名称。

如果要更改列标签,请使用其他线程Windows Powershell Rename Column Heading CSV file

中的方法
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '<=' | Select-Object @{ expression={$_.InputObject}; label='ComputerName' } | Export-Csv sccm-only.csv -NoTypeInformation

此外,只需更改SideIndicator比较以获取两个系统中的计算机,或仅在eWPT中:

# Only in eWPT
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '=>' | Select-Object @{ expression={$_.InputObject}; label='ComputerName' } | Export-Csv sccm-only.csv -NoTypeInformation

# In both SCCM and eWPT
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '==' | Select-Object @{ expression={$_.InputObject}; label='ComputerName' } | Export-Csv sccm-only.csv -NoTypeInformation

答案 4 :(得分:0)

$sccm=@(1,2,2,3)   
$wpt=@(2,4)

Compare-Object -ReferenceObject $sccm  -DifferenceObject $wpt | 
    Where-Object { $_.SideIndicator -eq '<=' } | 
    ForEach-Object  { Write-Output $_.InputObject }

这将返回1,2,3,此方法不正确