none
CSV Nach Datum suchen und um 10 Tage erhöhen RRS feed

  • Frage

  • Hallo Powershell Experten :)

    Ich habe folgendes Problem:

    Ich habe eine CSV Datei, dessen Datum ich verändern muss. Sprich aus dem 16.03.2020 soll 26.03 2020 werden bzw. aus zB dem 29.03.2020 soll dementsprechend auch der 07.04.2020 werden. Es reicht also nicht, einfach nur den Tag um die Zahl 10 zu erhöhen..

    Habe gerade keine Ahnung wie ich das realisieren soll, und mit RegEx bin ich auch nicht wirklich Fit. Ich hoffe sehr, dass ihr mir da weiter helfen könnt :)

    Hier auch ein Ausschnitt aus der CSV:

    "ArtikelNr";"Bestand";"Lieferzeit";"Bestandsmenge";"ETA";
    "090509";"0";"";"";;
    "090510";"0";"";"";;
    "095011";"5";"";"";;
    "CCWAV01";"5";"";"";;
    "CCWAV09";"5";"";"";;
    "CHSAI04";"5";"";"";05.02.2020;
    "CHSAI04F";"0";"";"";;
    "CHSAI06";"5";"";"";;
    "CHSAI07";"5";"";"";05.02.2020;
    "CHSAI07F";"0";"";"";;
    "CHSAI09";"0";"";"";;
    "CHSAI11";"0";"";"";;
    "CHSAIL";"0";"";"";;
    "CHSAIP";"0";"";"";;
    "CHSAIPBL";"0";"";"";;
    "CHSAIS";"0";"";"";;
    "CHVAL01";"5";"";"";05.02.2020;
    "CHVAL03";"5";"";"";;
    "CHVAL05";"0";"";"";;
    "CHVAL06";"5";"";"";05.02.2020;
    "CHVAL07";"5";"";"";05.02.2020;
    "CHVAL08";"5";"";"";05.02.2020;
    "CHVAL11";"0";"";"";;
    "CHVAL12";"5";"";"";;
    "CHVALC";"5";"";"";;
    "CPSB-002";"5";"";"";;
    "CPSB-CO2-001";"5";"";"";;
    "D5-1124-OD";"5";"";"";;
    "D5-1125-MC";"5";"";"";;
    "D5-1319";"0";"";"";;
    "D5-1334-B";"0";"";"";;
    

    Wie ihr sehen könnt, ist auch nicht immer ein Datum vorhanden...

    Es wäre super, wenn ihr mir eine Lösung schreiben könntet und vllt kurz erklären könntet, was da vorsich geht. Vllt stelle ich es mir ja komplizierter vor als es in Wahrheit ist ;)

    Vielen Herzlichen Dank!


    Daniel

    Samstag, 14. März 2020 17:49

Antworten

  • Moin,

    regex brauchst Du hier nicht. Mit 

    Import-CSV -Path <Deine Datei> -Delimiter ";"

    liest Du die Datei in einen Array von Objekten. Jedes dieser Objekte hat die Property "ETA", wo ab und zu ein Datum steht. Du kannst also in der Schleife mit 

    $_.ETA -as [datetime]

    die Angabe aus der CSV in ein Datum/Zeit-Format konvertieren. Gelingt dies (also dirt, wo das Datum steht), kannst Du für das so gewonnene Datetime-Objekt die Methode 

    .AddDays(10)

    aufrufen, und das Ganze mit 

    Get-Date <erhöhter Wert> -Format "dd.MM.yyyy"

    wieder zu einem String im gewünschten Format konvertieren.

    Wenn Du einen fertigen Code hast und irgendwo Probleme auftreten, kannst Du das Zwischenergebnis gerne hier posten und bekommst Hilfe. Skripte auf Bestellung gibt es hier nicht.

     

    Evgenij Smirnov

    http://evgenij.smirnov.de

    Samstag, 14. März 2020 18:16
  • Das ist es! Perfekt, ich danke dir herzlich :)

    Hier noch mal die fertigen Befehle:

    # Lieferzeit um 10 Tage erhoehen
    $CSV=Import-CSV -Path $LocalFileASCII -Delimiter ";"
    for ($i = 0; $i -lt $CSV.Count; $i++) {
        $ETA = $CSV.ETA[$i]
        if ("" -ne $ETA) {
            $ETA=[datetime]::ParseExact($ETA,'dd.MM.yyyy',$null)
            $ETA = $ETA.AddDays(10)
            $ETAneu = Get-Date $ETA -Format "dd.MM.yyyy"
            $CSV[$i].ETA = $ETAneu
        }
    }


    Daniel

    Samstag, 14. März 2020 22:27

Alle Antworten

  • Moin,

    regex brauchst Du hier nicht. Mit 

    Import-CSV -Path <Deine Datei> -Delimiter ";"

    liest Du die Datei in einen Array von Objekten. Jedes dieser Objekte hat die Property "ETA", wo ab und zu ein Datum steht. Du kannst also in der Schleife mit 

    $_.ETA -as [datetime]

    die Angabe aus der CSV in ein Datum/Zeit-Format konvertieren. Gelingt dies (also dirt, wo das Datum steht), kannst Du für das so gewonnene Datetime-Objekt die Methode 

    .AddDays(10)

    aufrufen, und das Ganze mit 

    Get-Date <erhöhter Wert> -Format "dd.MM.yyyy"

    wieder zu einem String im gewünschten Format konvertieren.

    Wenn Du einen fertigen Code hast und irgendwo Probleme auftreten, kannst Du das Zwischenergebnis gerne hier posten und bekommst Hilfe. Skripte auf Bestellung gibt es hier nicht.

     

    Evgenij Smirnov

    http://evgenij.smirnov.de

    Samstag, 14. März 2020 18:16
  • Okay alles klar. Danke dir, ich probiere das direkt mal aus und melde mich dann nochmal :)

    Daniel

    Samstag, 14. März 2020 20:09
  • Okay, hab das mal in etwa so angewendet und es hat soweit geklappt! :) Jedoch habe ich noch Probleme damit den neuen Wert korrekt in die CSV zu schreiben.

    Aktuell steht beim Abruf mit "$CSV.ETA" noch die alten Daten raus.. dabei schreibe ich das doch eigentlich aktuell wieder in das Array, oder nicht?

    Hier wäre das bisherige Skript:

    # Lieferzeit um 10 Tage erhoehen
    $CSV=Import-CSV -Path $LocalFileASCII -Delimiter ";"
    for ($i = 0; $i -lt $CSV.Count; $i++) {
        $ETA = $CSV.ETA[$i]
        if ("" -ne $ETA) {
            $ETA=[datetime]::ParseExact($ETA,'dd.MM.yyyy',$null)
            $ETA.AddDays(10)
            $ETAneu = Get-Date $ETA -Format "dd.MM.yyyy"
            $CSV.ETA[$i] = $ETAneu
        }
    }


    Daniel

    Samstag, 14. März 2020 20:46
  • Moin,

    versuch mal, statt  $CSV.ETA[$i] lieber  $CSV[$i].ETA ;-)


    Evgenij Smirnov

    http://evgenij.smirnov.de

    Samstag, 14. März 2020 22:00
  • Jup, das war bestimmt auch ein Fehler.

    Aber es geht irgendwie immer noch nicht.... Ich habe es bereits auch mit

    (Get-Date $ETA -Format "dd.MM.yyyy") | Set-Content $CSV[$i].ETA

    versucht. Beim Aufruf mit "$CSV.ETA" kommt weiterhin das ursprüngliche Datum raus :/


    Daniel

    Samstag, 14. März 2020 22:08
  • Moin,

    $ETA.AddDays(10) erhöht ja nicht den Wert von $ETA, sondern gibt den um 10 Tage erhöhten Wert aus. Willst Du den Wert der Variablen erhöhen, musst Du ihn wieder zuweisen:

    $ETA = $ETA.AddDays(10)


    Evgenij Smirnov

    http://evgenij.smirnov.de

    Samstag, 14. März 2020 22:20
  • Das ist es! Perfekt, ich danke dir herzlich :)

    Hier noch mal die fertigen Befehle:

    # Lieferzeit um 10 Tage erhoehen
    $CSV=Import-CSV -Path $LocalFileASCII -Delimiter ";"
    for ($i = 0; $i -lt $CSV.Count; $i++) {
        $ETA = $CSV.ETA[$i]
        if ("" -ne $ETA) {
            $ETA=[datetime]::ParseExact($ETA,'dd.MM.yyyy',$null)
            $ETA = $ETA.AddDays(10)
            $ETAneu = Get-Date $ETA -Format "dd.MM.yyyy"
            $CSV[$i].ETA = $ETAneu
        }
    }


    Daniel

    Samstag, 14. März 2020 22:27
  • du kannst eine Schleife im Powershell auch mit ForEach abbilden

    Beispiel für dich

    Import-Csv C:\temp\2.txt -Delimiter ";" | where ETA -NE "" |
             foreach {
            $ETA = $_.ETA -as [datetime]
            $ETA = $ETA.AddDays(10)
            write-host $_.ETA $ETA -ForegroundColor Yellow
         }
    


    Chris

    Sonntag, 15. März 2020 09:26
  • <korinthenkack>@Chris: Du hast die Schleife aber in Wirklichkeit mit Foreach-Object abgebildet ;-)

    Tatsächlich gibt es vier Wege, durch einen Array durchzuiterieren:

    $array | Foreach-Object {scriptblock mit $_}

    $array.Foreach({scriptblock mit $_})

    foreach ($item in $array) {scriptblock mit $item}

    for ($i = 0; $i -lt $array.Count; $i++) {scriptblock mit $array[$i]}

    Die Performance steigt in dieser Auflistung von oben nach unten ;-)

    </korinthenkack>


    Evgenij Smirnov

    http://evgenij.smirnov.de

    Sonntag, 15. März 2020 11:25
  • Der pipe ist tatsächlich langsamer (findet man inzwischen oft als Beispiel oder Muster in englishen Foren).

    die anderen drei sind fast gleich schnell. Danke für die Info. Ich hatte bisher immer gerne die 3 Variante verwendet da sie auch gut im Code lesbar ist.

    0,3280697
    0,281151
    0,2812051
    0,2811525


    Chris

    Sonntag, 15. März 2020 15:09
  • Der Vollständigkeit halber: Es gibt einen Fall, wo die Pipe schneller sein kann. Nämlich, wenn die Daten am Eingang allmählich entstehen (z.B. Get-Content, da werden die ersten Zeilen bereits in die Pipe "entlassen", noch bevor die Datei vollständig gelesen wurde) und am Ausgang keine "Sperre" eingebaut ist, die auf den letzten Datensatz wartet wie z.B. Sort-Object.

    Evgenij Smirnov

    http://evgenij.smirnov.de

    Sonntag, 15. März 2020 17:33
  • ForEach ist generell minimal langsamer, da zusätzlich eine Prüfung der Veränderung der Collection stattfindet.
    Sollte dies passieren (z.B. Add/Remove), wird ein ForEach mit Exception abgebrochen.
    Montag, 16. März 2020 08:42