Adding Results from Compare-Object to Array

2019-08-22 12:04发布

问题:

I have two files being compared, one a CSV and one a txt file. The CSV file has the information for around 5,000 servers and the txt file has only server names for around 3,000. The columns within the CSV are Name, OS, and Type. This is what I did to compare the objects:

$compareObject = Compare-Object -ReferenceObject $txtFile -DifferenceObject $csvFile.Name -IncludeEqual

After this, I was then given three options. Ones that are on both lists ==, ones that are only on the txt file =>, and ones that are only on the csv file =<.

What I'm trying to do is take the .SideIndicator for values that equal ==, and put that as a column within the $csvFile so I can eventually do If ($csvFile.SideIndicator -eq "==")...

So basically I'm trying to figure out how to write:

If (($csvFile.Name -like $compareObject.InputObject) -and ($compareObject.InputObject -eq "==") {
    (add .SideIndicator to CSV file)
}

I've tried placing a variable $count++ where I currently have add .SideIndicator... within my script to see how many results return, and it always returns 0.

Can someone help me out with this or give me some ideas?

回答1:

You want to pipe the results of Compare-Object to endable the filtering of SideIndicator like so:

$fields = "name", "street", "zip", "city"
Compare-Object -ReferenceObject $txtFile -DifferenceObject $csvFile.Name -IncludeEqual -Property $fields -PassThru | Where-Object {
    $_.SideIndicator -eq "=="
} | Select-Object $fields | Export-Csv ".\output.csv" -NoTypeInformation

Where $fields contain your CSV-Headers



回答2:

This may be way too complicated, but here you go:

Suppose this is your CSV file:

"Name","OS","Type"
"htew804","Windows","WindowsAutherServer"
"wddg9028","Windows","WindowsAutherServer"
"other321","Windows","WindowsBackupServer"

and this is the content of your text file:

wddg9028
test1234
htew804

Then this code:

$csvFile = 'D:\blah.csv'
$txtFile = 'D:\names.txt'

# import the .csv file
$csv = Import-Csv -Path $csvFile
# read the .txt file which contains only server names, each on a separate line
$txt = Get-Content -Path $txtFile

$items = Compare-Object -ReferenceObject $txt -DifferenceObject $csv.Name -IncludeEqual -PassThru 
$result = foreach ($item in $items) {
    $name = $item.ToString()
    switch ($item.SideIndicator) {
        '<='  { 
            # the servername is only present in the text file
            [PSCustomObject]@{
                Name = $name
                OS = ''
                Type = ''
                SideIndicator = $item.SideIndicator
                Comment = "Name only found in $txtFile"
            }
            break
        }
        default  { 
            # '==' AND '=>': the servername is only present in the csv file or in both files
            $server = @($csv | Where-Object { $_.Name -eq $name })[0]
            [PSCustomObject]@{
                Name = $server.Name
                OS = $server.OS
                Type = $server.Type
                SideIndicator = $item.SideIndicator
                Comment = if ($item.SideIndicator -eq '==') { "Name found in both files" } else { "Name only found in $csvFile" }
            }
        }
    }
}
$result | Format-Table -AutoSize

produces this result:

Name     OS      Type                SideIndicator Comment                        
----     --      ----                ------------- -------                        
wddg9028 Windows WindowsAutherServer ==            Name found in both files       
htew804  Windows WindowsAutherServer ==            Name found in both files       
other321 Windows WindowsBackupServer =>            Name only found in D:\blah.csv 
test1234                             <=            Name only found in D:\names.txt

If you want this info to be written to a new CSV file, change the Format-Table -AutoSize into Export-Csv -Path 'D:\blah_updated.csv' -NoTypeInformation



回答3:

  • Taking Theo's sample files, but importing both files (the text file with -Header Name)
  • and Razorfen's -PassThru approach,
  • plus reversing the order to have the csv file as -Reference

It's as easy as this:

$csvFile = Import-Csv .\sample.csv
$txtFile = Import-csv .\sample.txt -Header Name

Compare-Object -Ref $csvFile -Dif $txtFile -Property Name -IncludeEqual -PassThru

to get this desired output:

Name     OS      Type                SideIndicator
----     --      ----                -------------
wddg9028 Windows WindowsAutherServer ==
htew804  Windows WindowsAutherServer ==
test1234                             =>
other321 Windows WindowsBackupServer <=

So both get a +1 from me.