narthan
Goto Top

Powershell CSV replace jeden 2.Fund

Guten Tag liebe Community und Experten,

ich habe aktuell ein Problem bzgl. UTC (Coordinated Universal Time) und der kommenden Zeitumstellung, das ich gerne mittels Powershell lösen würde.

Wir bekommen täglich mehrere CSV Dateien mit viertelstündigen Werten, diese werden mittels Zwischenschritt weiterverarbeitet und final in ein System eingespielt. Die CSV Dateien enthalten nur ein Datum und eine Uhrzeit, aber keine Zeitzonenangabe. Hier ein Ausschnitt einer Bsp. CSV:
"Datum";"Uhrzeit";"Position";"Wert"  
25.10.2020;01:30;A106;22.5
25.10.2020;01:45;A106;22.8
25.10.2020;02:00;A106;23.5
25.10.2020;02:15;A106;9.5
25.10.2020;02:30;A106;5.0
25.10.2020;02:45;A106;3.7
25.10.2020;02:00;A106;26.3
25.10.2020;02:15;A106;22.2
25.10.2020;02:30;A106;20.1
25.10.2020;02:45;A106;19.5
25.10.2020;03:00;A106;15.5
25.10.2020;03:15;A106;9.8
25.10.2020;03:30;A106;4.0
25.10.2020;03:45;A106;3.9
25.10.2020;04:00;A106;20.4

Dieser Ausschnitt wiederholt sich mehrere hundert Male, da mehrere Positionen enthalten sind. Ich würde nun gerne mittels Powershell nach den doppelten Zeiteinträgen suchen und jeden 2. Fund ersetzen. Z.B.
25.10.2020;02:00;A106;26.3
25.10.2020;02:15;A106;22.2
25.10.2020;02:30;A106;20.1
25.10.2020;02:45;A106;19.5
Ersetzen durch:
25.10.2020;02:01;A106;26.3
25.10.2020;02:02;A106;22.2
25.10.2020;02:03;A106;20.1
25.10.2020;02:04;A106;19.5

...sodass die CSV wie folgt aussieht:
...
25.10.2020;02:00;A106;23.5
25.10.2020;02:15;A106;9.5
25.10.2020;02:30;A106;5.0
25.10.2020;02:45;A106;3.7
25.10.2020;02:01;A106;26.3
25.10.2020;02:02;A106;22.2
25.10.2020;02:03;A106;20.1
25.10.2020;02:04;A106;19.5
...

Allerdings weiß ich nur den Befehl um sämtliche Funde zu finden und zu ersetzen. Gibt es eine Möglichkeit per Schleife und Skip die ersten Funde zu überspringen? Ich habe es mit einer Variablen und Modulo versucht, also es sollen nur Strings replaced werden, wenn Modulo 0 ist und das funktioniert auch, allerdings bin ich gerade zu doof die Ergebnisse inklusive der übrigen CSV Datei in einer Output Datei zu speichern. Hier mein aktueller Code:

$inputpath = 'C:\Users\XY\csv\'  
$outputpath = 'C:\Users\XY\output\'  
$datetoday = Get-Date -Format yyyyMMdd
$search1 = "02:00"  
$replace1 = "02:01"  

$Results = Get-ChildItem $inputpath -Filter *.csv | 
     Foreach-Object {
                $csvPath=$_.FullName
                $Filename=$_.BaseName
                $outputFile= ($outputpath+$Filename+"_"+$datetoday+".csv")  
                $e = $null 
                $n = 0                               
                
                foreach($e in (Get-Content -Path $csvPath | Where-Object {($_ -like '*02:00*')})) {  
                $n+=1

                if (-not ($n%2)){
                $e -replace $search1, $replace1 
                } 
                } 
}
$Results | Set-Content -Path $outputFile -Encoding UTF8

Meine daraus resultierende csv Datei, leider ohne Header und andere Zeilen. Ich verstehe auch warum, aber komme aktuell nicht auf die Lösung face-sad
25.10.2020;02:01;A106;26.3
25.10.2020;02:01;A107;401.1
25.10.2020;02:01;A108;58.0
25.10.2020;02:01;A109;98.7


Viele Grüße
narthan

Content-Key: 4396706856

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

Printed on: April 27, 2024 at 09:04 o'clock

Member: TK1987
Solution TK1987 Oct 25, 2022 at 17:51:41 (UTC)
Goto Top
Moin Narthan,

kann es gerade nicht testen, aber sofern ich mich nicht vertippt habe, müsste es so funktionieren:
$inputpath  = 'C:\Users\XY\csv'   
$outputpath = 'C:\Users\XY\output'   

Foreach ($File in Get-Childitem "$inputpath\*.csv") {  
  $CSV = Import-CSV -Delimiter ";" -Path $File  
  Foreach ($Datum in $CSV | Group Datum) {
    $i = 1
    Foreach ($Zeit in $Datum.Group | Group Uhrzeit | Where Count -gt 1) {
      $Zeit.Group[1].Uhrzeit = (Get-Date $Zeit.Group[1].Uhrzeit -Format "HH:")+$i.ToString("d2")  
      $i++
    }
  }
  $CSV | Export-Csv -NoTypeInformation -Delimiter ";" ("{0}\{1}" -f $outputpath,$File.name)  
}

Gruß Thomas
Member: narthan
narthan Oct 25, 2022 at 18:53:03 (UTC)
Goto Top
Hi Thomas,

vielen Dank! Damit hat es geklappt face-smile
Da die richtigen CSV doch noch etwas umfangreicher als der Ausschnitt sind, musste ich noch ein paar Groups ergänzen, aber hat einwandfrei funktioniert!

Kannst du mir bitte noch die Zeile erklären, die verstehe ich nicht so ganz:
$Time.Group[1].Time = (Get-Date $Time.Group[1].Time -Format "HH:")+$i.ToString("d2")  

Vielen Dank und schönen Abend
narthan
Member: TK1987
Solution TK1987 Oct 25, 2022 at 19:59:36 (UTC)
Goto Top
Zitat von @narthan:
Kannst du mir bitte noch die Zeile erklären, die verstehe ich nicht so ganz:
$Time.Group[1].Time = (Get-Date $Time.Group[1].Time -Format "HH:")+$i.ToString("d2")  
$Time ist jeweils eine Gruppe aus Zeilen, bei der Datum und Uhrzeit gleich sind.
.Group[1] gibt von dieser jeweils die 2. Zeile (also index 1) aus
.Uhrzeit ist die Spalte Uhrzeit aus dieser Zeile.

Diese wird neu gesetzt. Die Stunden bleiben ja, also habe ich mit Get-Date ein datetime-objekt erzeugt und über -Format "HH:" nur noch die Stunden und den Doppelpunkt ausgegeben.
Alternativ hätte man hier natürlich auch mit .Substring(0,3) arbeiten können.

Was jetzt noch fehlt sind also die Minuten - diese kommen aus der aufsteigenden Integervariable $i. Diese wird mit .ToString("d2") 2-stellig ausgegeben.

Gruß Thomas
Member: narthan
narthan Oct 26, 2022 at 09:20:04 (UTC)
Goto Top
Hallo Thomas,

erneut vielen Dank! Super Erklärung!

Viele Grüße und einen schönen Tag
narthan