philipp711
Goto Top

Vergleich zweier CSV-Dateien über Powershell-Script

Hallo,

ich habe eine Verständnisfrage zur "Programmierung" eines Powershell-Scripts. Es geht darum, zwei Listen miteinander zu vergleichen bzw. herauszufinden ob ein Eintrag in Liste 1 auch in Liste 2 vorhanden ist.

Ein Konkretes Beispiel wäre z.B. die aktuelle Meltdown/Spectre Sicherheitslücke. Der Hersteller unserer Client- und Serversysteme hat eine Liste mit "affected Models" veröffentlicht. Durch das Inventarisierungssystem erhalte ich eine Liste unseres Inventars mit Modellbezeichnungen. Ziel ist es herauszufinden, welche Systeme konkret betroffen sind. Mein Gedanke war mit zwei verschachtelten schleifen das aktuelle Gerät aus der Inventarliste mit der kompletten "affected Liste" zu vergleichen. Bei einem Treffer soll dies ausgegeben werden.

Code:
$inventar = Import-Csv '.\inventar.csv' -Delimiter ';'  
$affected = Import-Csv '.\affected.csv' -Delimiter ';'  

ForEach($computer in $inventar){

    ForEach($model in $affected){

        if ($computer.Typ -eq $model.Bezeichnung){

        $computer.Name

        }

    }
}

Input Inventar.csv:

Name;Typ
PC01;A512
PC02;P400
PC03;P400
PC04;P400
PC05;P400
PC06;A512
PC07;A530
PC39;P2530
PC40;P410
PC41;P410
PC42;W280
PC43;P410
PC64;P410
PC65;P410
PC66;P410
PC67;P410
PC68;P420
PC69;P410
PC70;P400
PC71;P410
PC72;E420
PC73;P410
PC74;P420
PC85;P420

Input affected.csv:

Bezeichnung
A512 
P410
P420

Ergebnis:
PC40
PC41
PC43
PC64
PC65
PC66
PC67
PC68
PC69
PC71
PC73
PC74
PC85

-> PC01 & PC06 fehlen im Ergebnis...Ich verstehe allerdings nicht warum...

P.S.: Die Input-Listen sind zum bessern Überblick verkürzt. Im "Original" fehlen noch weitere Modelle/Computer

Content-Key: 361898

Url: https://administrator.de/contentid/361898

Ausgedruckt am: 19.03.2024 um 05:03 Uhr

Mitglied: 135185
135185 21.01.2018 aktualisiert um 17:04:32 Uhr
Goto Top
Schleifen überflüssig.
Hier steht schon wie das geht, compare-object ist dein Freund ...
Auslesen und Vergleichen Zweiter CSV Dateien Powershell

Einfach Mal unten unter deinem Thread in die Links schauen face-smile
PC01 & PC06 fehlen im Ergebnis...Ich verstehe allerdings nicht warum
Da sind gaaanz viele Leerzeichen am Ende der Zeile face-wink. Hier wäre dann trim() dein Freund.
  if ($computer.Typ.trim() -eq $model.Bezeichnung.trim()){ 
Gruß Sepp
Mitglied: Philipp711
Philipp711 21.01.2018 aktualisiert um 18:05:03 Uhr
Goto Top
Danke, der Trim() hilft - das war es! Allerdings möchte ich noch ein wenig weiter üben...ich würde die gefundenen Computer jetzt noch gerne in ein Array packen...zur weiteren Verarbeitung.

Dafür habe ich ein Array definiert

Liste = @()

und in der IF-Verzweigung die Zeile hinzugefügt

Liste =+ $computer.Typ

Hier schmeißt er den Fehler raus

Der Wert "P556" kann nicht in den Typ "System.Int32" konvertiert werden. Fehler: "Die Eingabezeichenfolge hat das falsche Format."  
In C:\Users\philipp.menges\Desktop\check_affected.ps1:13 Zeichen:9
+         $erg1 =+ $computer.Typ
+         ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) , RuntimeException
    + FullyQualifiedErrorId : InvalidCastFromStringToInteger

Auch hier verstehe ich nicht, warum er die Inhalte in einen Integer konvertieren will...
Mitglied: 135185
135185 21.01.2018 aktualisiert um 20:16:43 Uhr
Goto Top
Du stellst dir selbst ein Bein, schreib das Plus vor das Gleichheitszeichen ... dann jeht dat och.

Und Liste ist keine Variable,da hast du das Dollarzeichen vor dem Namen vergessen, das war aber vermutlich nur ein Typo.
Mitglied: colinardo
colinardo 22.01.2018 aktualisiert um 10:33:01 Uhr
Goto Top
Servus @Philipp711 ,
hier eine vereinfachte Variante um das ganze mit compare-object zu realisieren.
# Inventar einlesen inkl. Bereinigun der Spaces
$inventar = Import-Csv '.\inventar.csv' -Delimiter ';' | select Name,@{n='Typ';e={$_.Typ.Trim()}}  
# Affected einlesen und eine Eigenschaft schaffen die den selben Namen wie in der Inventar-Liste hat, damit ein Vergleich via 'Compare-Object' möglich ist 
$affected = Import-Csv '.\affected.csv' -Delimiter ';' | select @{n='Typ';e={$_.Bezeichnung.Trim()}}  
# Vergleich der Listen anhand der Eigenschaft 'Typ', Ausgegeben wird dann ein Array der PC Namen 
$computer = Compare @($inventar) @($affected) -Property Typ -IncludeEqual -ExcludeDifferent -PassThru | select -Expand Name
# Ausgabe des Arrays
$computer
Compare-Object ist sehr mächtig, solltest du dir unbedingt mal ansehen. Ich nutze es fast täglich für den Vergleich von Objekten in der Powershell, spart einem mächtig viel Schreibarbeit.

Falls du dich fragst was das hier für ein Konstrukt ist:
select @{n='Typ';e={$_.Typ.Trim()}} 
Das nennt man calculated property und ist schnelle Methode einem Objekt in der Pipeline benutzerdefinierte Eigenschaften zu verpassen.

Grüße Uwe