none
Textdateien ohne Trennzeichen in csv verwandeln RRS feed

  • Frage

  • Guten Abend,

    bin noch am Lernen mit Powershell, hänge gerade an einer Anforderung fest.

    Habe eine Testdatei mit >20000 Zeilen. Feste Spaltenbreiten.

    Z.B. Name            Firma          Abteilung             Raum                  Telefon

    Wie kann ich die aufbereiten in eine CSV-Datei ?

    Die zweite Datei finde ich noch schlimmer:

    Firma    Name           Teilenummer        Typ
    Muster  Meier, Hans  123456                PC
                                     46465                 Bildschirm

    Wieviele Zeilen es pro Person gibt, ist unterschiedlich. Manche haben nur eine Zeile, manche haben 15. Wie kann ich eine CSV-Datei erzeugen, die folgendes ausgibt:

    Muster;Meier, Hans;123456;PC
    Muster;Meier, Hans;46465;Bildschirm

    Am Orignialformat kann ich nichts ändern, daher wollte ich es via Powershell aufbereiten.

    Freue mich über Hinweise.

    CU,

    Axel

    Dienstag, 13. September 2016 22:25

Antworten

  • Moin,

    mit "von Tabelle zu Tabelle gleich" meinte ich natürlich "von Tabelle zu Tabelle derselben Art" ;-)

    Feste Breite:

    Sagen wir mal, Deine Spalten beginnen bei 1, 22, 44, 64 und 78. Dann sieht die primitive Lösung so aus:

    $infile = "c:\temp\tab1.txt"
    $outfile = "c:\temp\tab1.csv"
    
    $lines = Get-Content $infile
    if (Test-Path $outfile ) { Remove-Item $outfile }
    foreach ($line in $lines) {
        $name = $line.Substring(0,21).Trim()
        $company = $line.Substring(21,22).Trim()
        $dept = $line.Substring(43,20).Trim()
        $room = $line.Substring(63,14).Trim()
        $phone = $line.Substring(77).Trim()
        $outline = "`"$name`",`"$company`",`"$dept`",`"$room`",`"$phone`""
        $outline | Out-File $outfile -Append
    }

    Natürlich kann man es noch verfeinern, z.B. in der Annahme, dass die Spaltenköpfe keine Leerzeichen enthalten, die Positionen aus der Kopfzeile auslesen, oder die Positionen zu Begin als Array oder Hashtable (dann inklusive Namen) zu hinterlegen.

    Und nun mit mehrerern Detailzeilen pro Name + Company (Spaltenbreiten sind dieselben, nur halt eine weniger):

    $infile = "c:\temp\tab2.txt"
    $outfile = "c:\temp\tab2.csv"
    
    $lines = Get-Content $infile
    if (Test-Path $outfile ) { Remove-Item $outfile }
    $name = ""
    $company = ""
    foreach ($line in $lines) {
        $xname = $line.Substring(0,21).Trim()
        $xcompany = $line.Substring(21,22).Trim()
        $part = $line.Substring(43,20).Trim()
        $type = $line.Substring(63).Trim()
        if ($xname -ne '') {
            $name = $xname
        }
        if ($xcompany -ne '') {
            $company = $xcompany
        }
    
    
        $outline = "`"$name`",`"$company`",`"$part`",`"$type`""
        $outline | Out-File $outfile -Append
    }

    Viel Spaß damit :-)

    EDIT: Bei 20.000 Zeilen kann es sich durchaus lohnen, über effizienteres Lesen nachzudenken, hier am Beispiel des 2. Beispiels:

    $infile = "c:\temp\tab2.txt"
    $outfile = "c:\temp\tab2.csv"
    
    #erst mal nur die Datei öffnen, noch nicht einlesen...
    $lines = [System.IO.File]::OpenText($infile)
    
    if (Test-Path $outfile ) { Remove-Item $outfile }
    $name = ""
    $company = ""
    #...und nun Zeile für Zeile einlesen, bis er $null einliest
    while ($null -ne ($line = $lines.ReadLine())) {
        $xname = $line.Substring(0,21).Trim()
        $xcompany = $line.Substring(21,22).Trim()
        $part = $line.Substring(43,20).Trim()
        $type = $line.Substring(63).Trim()
        if ($xname -ne '') {
            $name = $xname
        }
        if ($xcompany -ne '') {
            $company = $xcompany
        }
    
    
        $outline = "`"$name`",`"$company`",`"$part`",`"$type`""
        $outline | Out-File $outfile -Append
    }


    Evgenij Smirnov

    msg services ag, Berlin -> http://www.msg-services.de
    my personal blog (mostly German) -> http://it-pro-berlin.de
    Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
    Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com

    In theory, there is no difference between theory and practice. In practice, there is.



    Mittwoch, 14. September 2016 21:07

Alle Antworten

  • Moin, ist es für eine regelmäßige Konvertierung gedacht und falls ja: Sind die Spaltenbreiten auch global fix, sprich: von Tabelle zu Tabelle gleich? Die zweite Herausforderung ist übrigens nicht schlimm: Du speicherst den ersten Teil weg, sobald er nicht leer ist, und bei der Ausgabe gibst Du immer den gespeicherten Wert aus...

    Evgenij Smirnov

    msg services ag, Berlin -> http://www.msg-services.de
    my personal blog (mostly German) -> http://it-pro-berlin.de
    Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
    Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com

    In theory, there is no difference between theory and practice. In practice, there is.

    Mittwoch, 14. September 2016 05:00
  • Moin Moin, 

    ist als regelmäßige Konvertierung gedacht. 

    Die beiden Tabellen haben unterschiedlich breite Spalten, werde zwei Scripte erstellen. 

    Kannst Du mir einen Tipp geben, wie ich das mit dem "wegspeichern des ersten Teils" machen kann bzw. wie ich die festen Spaltenbreiten in Powershell hinterlege ? 

    Thx.

    CU,

    Axel

    Mittwoch, 14. September 2016 20:17
  • Moin,

    mit "von Tabelle zu Tabelle gleich" meinte ich natürlich "von Tabelle zu Tabelle derselben Art" ;-)

    Feste Breite:

    Sagen wir mal, Deine Spalten beginnen bei 1, 22, 44, 64 und 78. Dann sieht die primitive Lösung so aus:

    $infile = "c:\temp\tab1.txt"
    $outfile = "c:\temp\tab1.csv"
    
    $lines = Get-Content $infile
    if (Test-Path $outfile ) { Remove-Item $outfile }
    foreach ($line in $lines) {
        $name = $line.Substring(0,21).Trim()
        $company = $line.Substring(21,22).Trim()
        $dept = $line.Substring(43,20).Trim()
        $room = $line.Substring(63,14).Trim()
        $phone = $line.Substring(77).Trim()
        $outline = "`"$name`",`"$company`",`"$dept`",`"$room`",`"$phone`""
        $outline | Out-File $outfile -Append
    }

    Natürlich kann man es noch verfeinern, z.B. in der Annahme, dass die Spaltenköpfe keine Leerzeichen enthalten, die Positionen aus der Kopfzeile auslesen, oder die Positionen zu Begin als Array oder Hashtable (dann inklusive Namen) zu hinterlegen.

    Und nun mit mehrerern Detailzeilen pro Name + Company (Spaltenbreiten sind dieselben, nur halt eine weniger):

    $infile = "c:\temp\tab2.txt"
    $outfile = "c:\temp\tab2.csv"
    
    $lines = Get-Content $infile
    if (Test-Path $outfile ) { Remove-Item $outfile }
    $name = ""
    $company = ""
    foreach ($line in $lines) {
        $xname = $line.Substring(0,21).Trim()
        $xcompany = $line.Substring(21,22).Trim()
        $part = $line.Substring(43,20).Trim()
        $type = $line.Substring(63).Trim()
        if ($xname -ne '') {
            $name = $xname
        }
        if ($xcompany -ne '') {
            $company = $xcompany
        }
    
    
        $outline = "`"$name`",`"$company`",`"$part`",`"$type`""
        $outline | Out-File $outfile -Append
    }

    Viel Spaß damit :-)

    EDIT: Bei 20.000 Zeilen kann es sich durchaus lohnen, über effizienteres Lesen nachzudenken, hier am Beispiel des 2. Beispiels:

    $infile = "c:\temp\tab2.txt"
    $outfile = "c:\temp\tab2.csv"
    
    #erst mal nur die Datei öffnen, noch nicht einlesen...
    $lines = [System.IO.File]::OpenText($infile)
    
    if (Test-Path $outfile ) { Remove-Item $outfile }
    $name = ""
    $company = ""
    #...und nun Zeile für Zeile einlesen, bis er $null einliest
    while ($null -ne ($line = $lines.ReadLine())) {
        $xname = $line.Substring(0,21).Trim()
        $xcompany = $line.Substring(21,22).Trim()
        $part = $line.Substring(43,20).Trim()
        $type = $line.Substring(63).Trim()
        if ($xname -ne '') {
            $name = $xname
        }
        if ($xcompany -ne '') {
            $company = $xcompany
        }
    
    
        $outline = "`"$name`",`"$company`",`"$part`",`"$type`""
        $outline | Out-File $outfile -Append
    }


    Evgenij Smirnov

    msg services ag, Berlin -> http://www.msg-services.de
    my personal blog (mostly German) -> http://it-pro-berlin.de
    Windows Server User Group, Berlin -> http://www.winsvr-berlin.de
    Mark Minasi Technical Forum, reloaded -> http://newforum.minasi.com

    In theory, there is no difference between theory and practice. In practice, there is.



    Mittwoch, 14. September 2016 21:07