【问题标题】:Find items which are in array1 but NOT in array2查找在 array1 但不在 array2 中的项目
【发布时间】:2014-10-04 08:31:10
【问题描述】:

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

现在我需要提取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 中的那些...

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

更新

我仍然没有得到正确的输出,在 Excel 中使用这个公式:

输出如下:

表示有些在这里,有些不在。 powershell中的输出是这样的

表示 0KB 是空的。

$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 的列名(或它的名称)都是“计算机名”

知道我做错了什么吗?这两个计算机数组都是从 SQL 和哈希表中生成的(我认为它被称为):@{Computername=......}@{Computername....,类似这样。

更新 2

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

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

通过删除 Hashtable 的 Header 并让数组充满字符串的效果非常棒......即使 -Property computername 也不起作用......:S

【问题讨论】:

  • 也许很高兴知道:我从两个不同服务器上的 PS SQL-Query 获得两个数组,当然还有两个不同的数据库 - 也许还有一种方法可以用 SQL 做到这一点?

标签: arrays powershell foreach


【解决方案1】:

使用compare-object cmdlet

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

示例:

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

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

将输出:

InputObject SideIndicator


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

这意味着值“2”在两个对象上,“1”和“3”仅在“左侧”(即参考对象)上,而“4”仅在差异对象上

【讨论】:

  • 嘿,首先,感谢您的帮助....我试过了,输出很乱...我看不出它背后的逻辑,有些计算机处理正确(有效。在 1 和 2 中,所以整理出来),但有些在两个文件中,仍然被导出到这个列表 - 知道这是怎么来的吗?
【解决方案2】:

如下使用compare-object

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

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

更正:

上面的代码适用于DifferenceObject被保证是ReferenceObject的一个子集的情况。但是,如果 DifferenceObject 中还有 ReferenceObject 中不存在的其他对象,它将失败。上面的代码返回任何存在于 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)

【讨论】:

  • +1 表示 passthru,但您缺少侧面指示器 Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt -PassThru | ?{$_.sideIndicator -eq "&lt;="}
【解决方案3】:

您可以使用-contains 和-notcontains

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

【讨论】:

    【解决方案4】:

    Compare-Object 方法确实是最好的。尚未解决的是 Excel 文件的干净输出。

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

    将产生两列。一个带有“InputObject”和您的计算机名称,另一列带有“SideIndicator”和一堆带有“

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

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

    这将为您提供一个标有“InputObject”的列和您的计算机名称。

    如果要更改列标签,请使用另一个线程的方法,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
    

    【讨论】:

      【解决方案5】:
      $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,这个方法不正确

      【讨论】:

        猜你喜欢
        • 2012-02-20
        • 2021-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-19
        • 2017-11-11
        相关资源
        最近更新 更多