none
Felder aus einer CSV-Datei auslesen und nach Kriterien weiterverarbeiten RRS feed

  • Frage

  • Hallo

    Ich will in meinem Skript eine CSV-Datei einlesen.

    Je nachdem, was in "Spalte 2" steht, sollen diese Daten weiter verarbeitet werden.

    Name,Wohnort
    Hans,Wien
    Erich,Berlin
    Karl,Wien
    Michael,Zuerich
    ...

    Nun soll der erste Name ausgelesen werden, bei dem der Wohnort "Wien" ist(nur dieser) und in die Variable $WohnortWien eingefügt werden.
    Danach soll in der CSV-Datei eine Änderung gemacht werden, indem der Wohnort auf "extern" geändert wird.

    D.h. beim ersten Vorgang würde Hans in die Variable $WohnortWien geschrieben und Wien zu extern geändert werden, beim zweiten Karl usw.

    Hoffe ihr könnt mir helfen 

    Gruss AndIBM

    Freitag, 1. Februar 2013 13:15

Antworten

  • Hallo

    Ich arbeite noch nicht lang mit Power Shell, da hast du Recht. Aber, da ich den eigentlichen Zweck nicht schreiben wollte, habe ich es ein wenig umformuliert(Vielleicht ein bisschen unpassend :))

    Habe diesen Teil inzwischen mit einer Funktion gelöst.

    Wünsche dir ein schönes Wochenende

    ...
    function getBsp($file) {
        $imported_data = Import-Csv $file
    
        $index = $imported_data.Count - 1
    
        #Output to use for Bsp
        $Output = ""
    
        #separate arrays for imported data
        $new_Bsp = @()
        $new_BspStatus = @()
    
        #Write imported data in separate arrays
        for($i=0;$i -le $index;$i++) {
            $new_Bsp += @($imported_data[$i].Bsp)
            $new_BspStatus += @($imported_data[$i].status)
        }
    
        #find the first free Bsp, set status to used and write Bsp in variable
        for($i=0;$i -le $index;$i++) {
            if ($new_status[$i] -eq 'free') {
                $Output = $new_Bsp[$i]
                $new_status[$i] = 'used'
                break
            }
        }
        
        "Bsp,status" > $file
        
        for($i=0;$i -lt $new_Bsp.Count;$i++){
            #define line
            $Bsp = $new_Bsp[$i]
            $BspStatus = $new_status[$i]
            $line = "$Bsp,$BspStatus"
            
            #write line to file
            $line >> $file
        }
        
        return $Output
    }
    
    #################
    
    $Output = getBsp "E:\temp"
    #echo $Output
    ...

    Gruss AndIBM


    Freitag, 1. Februar 2013 15:07

Alle Antworten

  • Ich habe das Gefühl das du dies als Lernaufgabe bekommen hast?
    Hast du denn schon einen nicht Funktionierenden Code?

    Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
    Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
    My PowerShell Blog http://www.admin-source.info
    [string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
    German ? Come to German PowerShell Forum!

    Freitag, 1. Februar 2013 14:03
  • Hallo

    Ich arbeite noch nicht lang mit Power Shell, da hast du Recht. Aber, da ich den eigentlichen Zweck nicht schreiben wollte, habe ich es ein wenig umformuliert(Vielleicht ein bisschen unpassend :))

    Habe diesen Teil inzwischen mit einer Funktion gelöst.

    Wünsche dir ein schönes Wochenende

    ...
    function getBsp($file) {
        $imported_data = Import-Csv $file
    
        $index = $imported_data.Count - 1
    
        #Output to use for Bsp
        $Output = ""
    
        #separate arrays for imported data
        $new_Bsp = @()
        $new_BspStatus = @()
    
        #Write imported data in separate arrays
        for($i=0;$i -le $index;$i++) {
            $new_Bsp += @($imported_data[$i].Bsp)
            $new_BspStatus += @($imported_data[$i].status)
        }
    
        #find the first free Bsp, set status to used and write Bsp in variable
        for($i=0;$i -le $index;$i++) {
            if ($new_status[$i] -eq 'free') {
                $Output = $new_Bsp[$i]
                $new_status[$i] = 'used'
                break
            }
        }
        
        "Bsp,status" > $file
        
        for($i=0;$i -lt $new_Bsp.Count;$i++){
            #define line
            $Bsp = $new_Bsp[$i]
            $BspStatus = $new_status[$i]
            $line = "$Bsp,$BspStatus"
            
            #write line to file
            $line >> $file
        }
        
        return $Output
    }
    
    #################
    
    $Output = getBsp "E:\temp"
    #echo $Output
    ...

    Gruss AndIBM


    Freitag, 1. Februar 2013 15:07
  • Hallo Andi!
    Ich bin jetzt mal dazu gekommen deinen Code in Ruhe anzusehen.
    Das was du da machst, hat mit PowerShell wenig zu tun!
    Anscheinend hast du irgendwie nicht mitbekommen, das PowerShell Objekte verarbeitet.
    Siehe : http://www.it-visions.de/lserver/artikeldetails.aspx?b=4479

    Und : http://www.nt4admins.de/themen/powershell/artikel/objektorientierung-in-der-powershell.html

    CSV und XML werden beim einlesen in ein Array von PowerShell Objekten verwandelt.
    Diese Objekte kann man ähnlich wie in VBScript mit Ihren Eigenschaften (Properties) und Methoden nutzen!
    Ebenso solltest du statt For($i ….) das ForEach() Konstrukt verwenden.
    Du sparst dir dadurch nicht nur die Zähler Variablen, sondern ForEach() ist auch noch schneller als das For()!
    Ebenso gibt es in der PowerShell eine Vereinbarung wie man Cmdlets und Funktionen benennen sollte: Ver-Subsantiv.
    Wobei das Substantiv in der Einzahl ist.
    Ich zeige dir mal Langsam aufgebaut wie ich es machen würde.
    Angenommen die CSV Daten liegen in der Datei: D:\Temp\test.csv

    "Name,Wohnort","Hans,Wien","Erich,Berlin","Karl,Wien","Michael,Zuerich" | Out-File D:\temp\test.csv


    #Schick einfach mal diese Zeile ab dann siehst du,
    # du bekommst ein Array von Objekten zurück,
    #das in Tabellenform dargestellt wird.
    Import-CSV D:\temp\test.csv
    
    
    #Die einzelnen Werte der Objekte kannst du mit dem Punkt Operator auslesen.
    #Wobei die Überschriften der Tabelle die  in eben dargestellt wurde und
    #die Überschriften der CSV, die Property Namen sind, mit denen man die Werte ansprechen kann.
    ForEach($Objekt in Import-CSV D:\temp\test.csv) {
        $Objekt.Name
        $Objekt.Wohnort
    }

    Ein anders WICHTIGES Grundprinzip der PowerShell ist die Pipeline.
    Die Pipeline verbindet die Ausgabe eine Cmdlets mit der Eingabe eines anderen Cmdlets.
    Wie in einer Produktionsstraße wo ein Fließband die Ergebnisse von einem Roboter zu einem anderen Roboter zu Weiterverarbeitung Transportiert.

    # hier eine sehr kurze Pipeline mit nur 2 Akteuren
    # Import-CSV reicht die Objekte über das Pipeline Symbol | an Export-CSV zur Verarbeitung durch!
    # Das ergebnis der Pipeline liegt dann in der Datei D:\temp\test2.csv (keine Bild Ausgabe!)
    Import-CSV D:\temp\test.csv | Export-Csv D:\temp\test2.csv –NoTypeInformation

    Leider ist die ForEach() Schleife kein guter Pipeline Spieler und Export-CSV mag am liebsten Pipeline Input,
    deswegen verpacken wir diese in einer Funktion.
    Hierbei ist zu beachten das die Objekte als Ganzes zurückgegeben werden und nicht die einzelnen Properties.

    Function Get-Bsp {
        param ($Path)
    
        ForEach($Objekt in Import-CSV $Path) {
            $Objekt
        }
    }
    
    Get-Bsp D:\temp\test.csv | Export-Csv D:\temp\test2.csv –NoTypeInformation

    Grundlagen erklärt, nun geht es an die Verarbeitung:
    e nachdem, was in "Spalte 2" steht, sollen diese Daten weiter verarbeitet werden.
    Spalte 2 ist das Property „Wohnort“  in den Objekten!

    # Leere Variable ausserhalb der Funktion erstellen
    # um den ersten Namen eines Wiener abzuspeichern
    [String]$WohnortWien
    
    Function Get-Bsp {
    
        param ($Path)
    
        # CSV komplett in den Speicher laden sonnst, klappt das mit dem Überschreiben nicht!
        $Daten = Import-CSV $Path
        
        # übergeordnete Script Variable Leer initialisieren
        # Siehe: Get-Help about_scopes
        $Script:WohnortWien = ''
    
        $Objekte = @()
    
        ForEach($Objekt in $Daten) {
            
            # Wenn der Wohnort Wien ist und die Variable $WohnortWien noch leer ist
            # dadurch wir nur das erste gefundene Objekt geändert,
            # da die Variable nach dem ersten gefundenen nicht mehr leer ist!
            If (($Objekt.Wohnort -eq 'Wien') -and ($Script:WohnortWien -eq '') ) {
                # Variable mit dem Namen befüllen
                $Script:WohnortWien = $Objekt.Name
                # Wohnort auf extern ändern
                $Objekt.Wohnort = 'extern'
            }
    
            
            # Objekte (das erste ist geändert) wieder Ausgeben (in die Pipeline)
            $Objekt
    
        }
    
    }
    
    # Hier wird die eingabedatei mit den neuen Daten ÜBERSCHRIEBEN !!!!
    # Deshalb wird beim nächsten aufruf, der nächste Wohnort Wien geändert !
    $Objekte = Get-Bsp D:\temp\test.csv
    # Das Cmdlet Export-CSV ist sehr zickig ! Es möchte gerne Input von der Pipeline und hat keinen anfügemodus
    # ebenso hat es bei mir nicht direkt mit der Funktion in der pipleine gearbeitet
    # deswegen nutze ich hier das Array $Objekte als "zwischenhändler"
    $Objekte | Export-Csv D:\temp\test.csv –NoTypeInformation
    
    # Namen anzeigen der geändert wurde
    Write-Host "Ich habe den Wohnort von 'Wien' auf 'extern' bei dem Namen: $WohnortWien geändert!"

    Gute Links um PowerShell zu Lernen findest du hier:
    http://www.admin-source.de/BlogDeu/kostenlose-powershell-ebook-tutorial-workshop-howto

    Und hier in der Mitte des Threads Buchtips (Ich rate dir dringend eines anzuschaffen und zu lesen):
    http://social.technet.microsoft.com/Forums/de-DE/powershell_de/thread/84727252-3d5d-459e-b3a8-73a15807a807


    Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
    Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
    My PowerShell Blog http://www.admin-source.info
    [string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
    German ? Come to German PowerShell Forum!

    Samstag, 2. Februar 2013 13:29