Reputation: 299
I extracted two lists of computers from two different tools, Array1
and Array2
.
Now I need to extract the ones which are in Array1
, but not in Array2
.
I managed to get all the matching ones by doing this:
$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
But I still need the ones that are in $SCCMcomputer
but NOT in $eWPTcomputers
...
I've found some solutions on SO with other languages (e.g. Perl) but not for PowerShell.
UPDATE
I still don't get the correct output, in Excel with this formula:
the output looks like:
means some are here, some not. The output in powershell is like this
means 0KB is 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
And both Column Name (or what it's called) from SCCMcomptuers/eWPTcomputers is "Computername"
Any idea what I could be doing wrong? Both computer arrays are generated from SQL and in hashtables (I think it's called): @{Computername=......}@{Computername....
, something like this.
Update 2
foreach ($t in $sccmComputers) {
$Test1 += $t.computername
}
$Test2 = @()
foreach ($t in $ewptComputers) {
$Test2 += $t.computername
}
By removing the Header of the Hashtable and just having arrays full of strings works fantasctic..... even -Property computername
did not work... :S
Upvotes: 4
Views: 19163
Reputation: 21
$sccm=@(1,2,2,3)
$wpt=@(2,4)
Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt |
Where-Object { $_.SideIndicator -eq '<=' } |
ForEach-Object { Write-Output $_.InputObject }
This will return 1,2,3, this method is not correct
Upvotes: 0
Reputation: 2772
Use compare-object
as follows
Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt -passthru
This should give you just the objects in $sccm but not in $wpt.
CORRECTION:
The above code WILL work for the case where DifferenceObject is guaranteed to be a subset of ReferenceObject. It will FAIL, though, if there are additional objects in DifferenceObject that are not also present in ReferenceObject. The above code returns any objects which are present in EITHER ReferenceObject OR DifferenceObject but NOT in both.
To properly return ONLY objects in ReferenceObject that are not also present in DifferenceObject, the following code is required:
Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt |
Where-Object { $_.SideIndicator -eq '<=' } |
ForEach-Object { Write-Output $_.InputObject }
The where-object
clause ensures only objects that are present in ReferenceObject are passed down the pipeline.
The foreach-object
clause forces the output back to a simple array (ref: Converting Custom Object arrays to String arrays in Powershell - thanks Keith)
Upvotes: 2
Reputation: 71
The Compare-Object method is indeed the best. What hasn't been addressed yet is clean output to your Excel file.
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '<=' | Export-Csv sccm-only.csv -NoTypeInformation
will produce two columns. One with "InputObject" and your computer names, and another column with "SideIndicator" and a bunch of rows with "<=".
The easy fix is to select only the column you want:
Compare-Object $sccm $ewpt | ?{ $_.SideIndicator -eq '<=' | Select-Object InputObject | Export-Csv sccm-only.csv -NoTypeInformation
This will give you a single column labeled "InputObject" and your computer names.
If you want to change the column label, use the method from another thread, 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
Also, simply change the SideIndicator comparison to get those computers in both systems, or only in 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
Upvotes: 1
Reputation: 26150
use compare-object
cmdlet
Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt | ?{$_.sideIndicator -eq "<="} |select inputobject
example :
$sccm=@(1,2,3)
$wpt=@(2,4)
Compare-Object -ReferenceObject $sccm -DifferenceObject $wpt -IncludeEqual
will output :
InputObject SideIndicator
2 == 4 => 1 <= 3 <=
that means value "2" is on both objects, "1" and "3" only on "the left side" (ie the reference object), while "4" is only on the difference object
Upvotes: 12
Reputation: 19
You can use -contains
and -notcontains
$A1 ="asd","zxc","qwe",'a'
$A2 = "asd","zxc","bqwe",'b'
$A1,$A2 |
%{
$_|
%{
If ($A1 -contains $_ -and $A2 -notcontains $_) {$_}
}
}
Upvotes: 1