none
Zwei CSV - Dateien als Input und eine neue CSV - Datei als Output RRS feed

  • Frage

  • Hallo,

    ich bin noch Neuling mit Powershell, möchte aber gerne meine Aufgaben damit erledigen.

    Eine dieser Aufgaben ist es, Information aus zwei CSV-Dateien auszulesen und diese dann den Output in eine neue CSV-Datei schreiben.

    Konkret habe ich folgende Situation.

    CSV - Datei A mit einer Liste von Nummern

    Header A

    111 

    333

    555

    CSV - Datei B mit einer Liste von Nummern und Werten 

    Header B

    111, WertA111, WertB111, WertC111

    222, WertA222, WertB222, WertC222

    333, WertA333, WertB333, WertC333

    444, WertA444, WertB444, WertC444

    555, WertA555, WertB555, WertC555

    Output soll CSV - Datei C sein mit exact demselben Format wie B, aber soll nur die Nummer und Werte enthalten, die aus A ausgelesen wurden. Also in dem Fall:

    Header B

    111, WertA111, WertB111, WertC111

    333, WertA333, WertB333, WertC333

    555, WertA555, WertB555, WertC555

    Wie müssen die Befehle lauten, um so ein Konstrukt zu basteln?

    Wäre für jede Hilfe dankbar.

    Dienstag, 24. Februar 2015 07:55

Antworten

Alle Antworten

  • Hallo Tomde79!

    Als aller erstes MUSST du dir bei PowerShell merken:
    PowerShell Produziert und Verarbeitet Objekte kein Text!

    Die Befehle (in PowerShell sagt man Cmdlet), die du brauchst, sind Import-CSV und Export-CSV.
    Lies dir bitte die Bedienungsanleitung zu den beiden Cmdlets durch!

    Import-CSV

    Export-CSV

    Das Cmdlet Import-CSV macht aus jeder Zeile einer CSV Datei ein Objekt. Die Überschriften der Spalten sind die Namen der Properties.
    Um das Besser zu verstehen, lies mal meinen Artikel hier:

    Import-CSV WorkShop

    $ObjekteDateiA = Import-CSV -Path 'c:\Pfad\zur\DateiA.csv'
    
    Import-CSV -Path 'C:\Pfad\zur\DateiB.csv' | ForEach-object {
         # jede CSV Zeile ist hier als einzelnes Objekt in der automatisch generierten Variable mit
         # dem namen $_ verfügbar. Auf die Spalten kann man mit dem Spaltennamen und dem Punkt als Pfadangabe zugreifen.
         
         # Jedes Objekt in der CSV Datei A wird mit dem Wert von dem Aktuellen objekt aus der CSV Datei B verglichen 
         ForEach($ObjektA in $ObjekteDateiA) {
            If($ObjectA.A -eq $_.B) {
                # Werte sind gleich
                #Ausgabe in die Pipeline
                $_
            }
         }
    # Aus der Pipeline wird eine Neue Datei erstellt
    } | Export-CSV -NoTypeInformation -Path 'C:\Pfad\zur\DateiC.csv' -UseCulture


    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+

    • Als Antwort vorgeschlagen brima Dienstag, 24. Februar 2015 15:50
    • Bearbeitet Peter Kriegel Mittwoch, 25. Februar 2015 11:13
    Dienstag, 24. Februar 2015 09:31
  • Hallo Peter,

    vielen Dank für die Antwort. Als ich versucht habe, das Script auszuführen, bin ich auf folgende Probleme gestoßen.

    1) Parse-error weil eine der Header einen Bindestrich enthält.

    +  If($ObjectA.Partnumbers -eq $_.MARA- <<<< MATNR) {
        + CategoryInfo          : ParserError: (:) []、ParseException
        + FullyQualifiedErrorId : ExpectedValueExpression

    2) Die exportierte CSV-Datei enthält Gänsefüßchen, die ich dann händisch wieder entfernen müsste.

    3) Die exportierte CSV-Datei ist nicht im richtigen Format ausgegeben. Einige der Daten sind auf Japanisch und werden nicht korrekt dargestellt. Ist es möglich das Format wie UTF8 beim Export zu bestimmen?

    Mittwoch, 25. Februar 2015 01:11
  • Zu 1)

    Wenn deine Header Zeichen enthalten, die nicht verarbeitet werden können, musst du die Headerzeile vorher (von PowerShell) bearbeiten.

    Zu 2)

    Wenn man mit Export-CSV arbeitet, sollte man sich mit dem Grundlagen des CSV Format auskennen.

    Das CSV Format

    Man kann sich eine CSV Datei wie eine Excel Tabelle mit Überschriften (Englisch: header) für jede Spalte in der ersten Zeile vorstellen.
    Das CSV Format ist eigentlich eine Tabelle, die nur 2 Dimensionen hat, um Daten in Zellen darzustellen.
    Die Daten stehen in Spalten und Zeilen (oder auch X,Y).

    Das Dateiformat CSV steht für Englisch: Comma-Separated Values.
    Die Regeln zu Erstellung einer CSV Datei werden im RFC 4180 von der Internet Engineering Task Force (IETF) beschrieben.
    Siehe: http://tools.ietf.org/html/rfc4180
    Siehe Wikipedia: http://de.wikipedia.org/wiki/CSV_%28Dateiformat%29

    Der Text in einer CSV Datei muss den Regeln aus dem RFC 4180 entsprechen!

    Delimiter

    Für das Trennzeichen (Englisch: delimiter), das die einzelnen Datenspalten voneinander trennt, ist das Komma vorgesehen.
    Deshalb heißt das Dateiformat auch Comma Separated Values.

    Anführungszeichen

    Wenn die Daten selbst das Trennzeichen enthalten, dann wird das Datenfeld in Doppelte-Anführungszeichen gesetzt.
    Die Doppelten-Anführungszeichen wirken wie eine Paar Klammern, die das Datenfeld einschließen.

    Beispiel CSV Daten mit Trennzeichen (Komma) in den Daten:
    Daten1,Daten2,"Daten3, mit Komma",Daten4

    Wenn die Daten selbst Anführungszeichen enthalten dann werden die Anführungszeichen mit Anführungszeichen Maskiert. Die Anführungszeichen werden verdoppelt.

    Daten mit Anführungszeichen : "Daten "mit" Anführungszeichen"
    Anführungszeichen in CSV Maskiert: """Daten ""mit"" Anführungszeichen"""

    Auch Microsoft Excel versteht den Umgang mit den Anführungszeichen.

    Wenn man Microsoft Excel installiert hat und die CSV Datei doppelt klickt, dann müsste Excel die Datei öffnen und Anzeigen. Wenn nicht öffnet man Excel und öffnet dann die CSV Datei über das Datei öffnen Menü + Dialog. In Excel wird man sehen, dass die Anführungszeichen verschwunden sind und alle Daten stehen korrekt in ihren Zellen und Spalten.

    Jedes Programm das CSV verarbeitet, muss ebenso mit den Anführungszeichen umgehen können, da die Nutzung von Anführungszeichen zu den CSV Regeln gehört.


    Um die Anführungszeichen zu umgehen kann man in den meisten Programmen das Trennzeichen selber vorgeben.
    Dies kann man z,B. In der PowerShell mit dem -Delimiter Parameter bei den CSV Cmdlets.
    Da in Deutschland das Komma als Dezimaltrennzeichen genutzt wird, wird in deutschen CSV Dateien häufig das Semikolon als Alternatives Trennzeichen (Englisch: delimiter) benutzt.
    Aber auch hier können die Daten wieder das Semikolon enthalten und dann kommen die Anführungszeichen wieder zum Einsatz.


    3) Die exportierte CSV-Datei ist nicht im richtigen Format ausgegeben. Einige der Daten sind auf Japanisch und werden nicht korrekt dargestellt. Ist es möglich das Format wie UTF8 beim Export zu bestimmen?

    Das kannst du dir selbst beantworten, wenn du dir das Cmdlet Export-Csv richtig anschaust. Man sollte zu jedem Cmdlet das man benutzt die Anleitung lesen, wie ich oben schon gesagt habe :-) !
    hast du dort mal auf den Export-CSV Link geklickt und gelesen?

    Der Parameter -Encoding ist dein freund!


    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+

    Mittwoch, 25. Februar 2015 11:12
  • Hallo Peter,

    vielen Dank für die Tipps.

    Ja, ich weiß, dass die Anführungszeichen von Programmen wie Excel ohne Probleme verarbeitet werden. Allerdings wird das Ergebnis von einem Programm verarbeitet, dass die Anführungszeichen gar nicht verträgt. Daher muss ich diese wieder rausnehmen. Zudem schreibt mir Export-CSV noch eine Zeile dazu, die ich gar nicht gebrauchen kann, sodass ich die erste Zeile entfernen muss. Das habe ich dann so gelöst:

    $ObjekteDateiA = Import-CSV -Delimiter "`t" -Path 'C:\PINPOINT.TXT' -Header  "Partnumbers"

    Import-CSV -Delimiter "`t" -Path 'C:\Z_ZZD0024Z.TXT' -Header "MARA-MATNR","MARA-ERSDA","MARC-MTVER" | ForEach($_.'MARA-MATR') {
      
         ForEach($ObjektA in $ObjekteDateiA)
     {
            If($ObjektA.Partnumbers -eq $_.'MARA-MATNR') {
                $_
            }
         }

    } | Export-CSV -Delimiter "`t" -Encoding UTF8 -Path 'C:\Z_ZZD0024Z-NEW.TXT'

    (Get-Content 'C:\Z_ZZD0024Z-NEW.TXT' -Encoding UTF8) | Select-Object -Skip 1 |
    Foreach-Object {$_ -replace "`"", ""} | Set-Content 'C:\Z_ZZD0024Z-NEW.TXT' -Encoding UTF8



    • Bearbeitet Tomde79 Donnerstag, 26. Februar 2015 05:00
    Donnerstag, 26. Februar 2015 04:59
  • Zudem schreibt mir Export-CSV noch eine Zeile dazu, die ich gar nicht gebrauchen kann, sodass ich die erste Zeile entfernen muss.



    Auch hier muss ich dir sagen, wenn du dir das Cmdlet Export-Csv und die Dokumentation richtig anschaust, siehst du den Parameter -NoTypeInformation.

    Dieser unterdrückt die dämliche, zusätzliche Zeile mit den Typinformationen.

    So geht alles mit nur einer Pipeline:

    $ObjekteDateiA = Import-CSV -Delimiter "`t" -Path 'C:\PINPOINT.TXT' -Header  'Partnumbers'
    
    Import-CSV -Delimiter "`t" -Path 'C:\Z_ZZD0024Z.TXT' -Header 'MARA-MATNR','MARA-ERSDA','MARC-MTVER' | ForEach($_.'MARA-MATR') {
      
         ForEach($ObjektA in $ObjekteDateiA)
     {
            If($ObjektA.Partnumbers -eq $_.'MARA-MATNR') {
                $_
            }
         }
    
    } | ConvertTo-Csv -NoTypeInformation | ForEach-Object { $_ -replace '"', ''} | Out-File 'C:\Z_ZZD0024Z-NEW.TXT' -Force -Encoding UTF8


    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+

    Donnerstag, 26. Februar 2015 07:43