em-pie
Goto Top

Powershell - Wert aus Get-Content in DateTime konvertieren

Moin zusammen,

Ausgangslage
Es existiert ein Ordner mit ein paar (vielen) CSV-Dateien, der sporadisch um CSV-Dateien des selben Aufbaus ergänzt wird.

Aufbau der CSV (Die Header lauten anders, haben aber dennoch beknackte Texte, z. B. (m³))
Datum/Zeit;Toller Wert2 in (m³);Der Wert3 ist in l/h;Wert4
2022-01-04-06:27:57;327;21.4;8.105006;98
2022-01-05-06:27:57;303;18.3;8.065323;98
...

Ziel
Diese CSV-Files sollen eingelesen und am Ende in eine "große" CSV geschrieben werden.
Zudem müssen ein paar Konvertierungen durchgeführt werden. Beispielsweise muss das Datum auch als Datumsformat dargestellt werden. Der Bindestrich zwischen Datum und Uhrzeit ist irgendwie Mist.
Ferner muss aus den ganzen Dezimaltrennzeichen "." ein "," werden.

Was ich habe
$src = 'd:\tmp\myTests\data\*'  
$dst = 'd:\tmp\myTests\TheHoleContent.csv'  

$CSVfiles = Get-ChildItem -path $src -Include *.csv

foreach($file in $CSVfiles){
    
    $content = Get-Content -Path $file.FullName |
        Select-Object -Skip 1  @{Name = 'Timestamp'; Expression = { [datetime]::ParseExact($_."Datum/Zeit", 'yyyy-MM-dd-HH:mm:ss')}} |  
# Der Einfachheit wegen sind die anderen Spalten erstmal unberücksichtigt geblieben
        ConvertFrom-CSV -Delimiter ';'  

    $content
    $content | Export-CSV -Path $dst -Append -Delimiter ';'  
}

Mit dem -Skip 1 will ich die ersten Zeilen in den CSV-Files (=Header) übergehen. Dann habe ich aber das Problem, dass meine Properties keine Namen mehr haben.
Das Datum aus der Quelle soll als yyyy-MM-dd HH:mm:ss später gespeichert werden. Mein obiger Versuch ([datetime]::ParseExact()) ist eigentlich Quatsch, zu der Erkenntnis bin ich schon gekommen. Quatsch aus zwei Gründen: dadurch habe ich nicht das eigentlich gewollte Format und es funktioniert obendrein nicht
RegEx kann ich zwar einigermaßen lesen, Aktiv anwenden aber... sagen wir mal, wir sind uns noch nicht ganz grün face-big-smile. Mit RegEx kann ich vermutlich "irgendwie" das Datum passend konvertieren, da ich ja eigentlich nur den dritten Bindestrich durch ein Leerzechen ersetzen lassen müsste.

Ferner: Wie kann ich die einzelnen Properties ansprechen, wenn ich denen ja quasi den Header geklaut habe?
Wenn ihr mir bei dieser Frage helfen könnten, würde ich zumindest das Thema mit den Dezimaltrennzeichen rasch lösen können. Ich hab nur keine Idee, wie ich auf die Werte zugreifen kann, ohne einen sprechenden Namen zu haben.
Beispielsweise ist wäre es ja so kein Problem, aber die Spalten heißen leider nicht Col3, ...
@{Name = 'myValue3'; Expression = { $_.Col3 -replace ".", ","}}   


Bei meinen Recherchen habe ich bisher noch nicht das richtige gefunden. Wobei ich mal behaupte, dass ich schlicht nicht nach den richtigen Begriffen gesucht habe.

Könnt ihr mir hier ein wenig Nachhilfe geben?

Schon mal besten Dank an euch.


P.S. die Quelldateien entstammen einem Messsystem und lassen sich daher nicht modifizieren - das Wäre auch der von mir favorisierte Weg gewesen: Das Übel an der Wurzel anpacken.

Content-ID: 3654696465

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

Ausgedruckt am: 18.12.2024 um 12:12 Uhr

3479126418
Lösung 3479126418 15.08.2022 aktualisiert um 13:43:07 Uhr
Goto Top
Da das Datum ja eh schon fast fertig ist und nur der Bindestrich stört, lohnt es sich fast gar nicht das Teil in ein Datum zu konvertieren, da ja wohl eh nicht damit gearbeitet/gerechnet werden muss reicht ein replace.
$src = 'd:\tmp\myTests\data'  
$dst = 'd:\tmp\TheHoleContent.csv'  
$CSVfiles = Get-ChildItem -path $src -File -Filter *.csv

foreach($file in $CSVfiles){
    $csv = Get-Content $file | select -Skip 1 | ConvertFrom-CSV -Delimiter ";" -Header 'Spalte1','Spalte2','Spalte3','Spalte4','Spalte5'  
    foreach($line in $csv){
        $line.Spalte1 = $line.Spalte1 -replace '(\d{4}-\d{2}-\d{2})-(\d{2}:\d{2}:\d{2})','$1 $2'  
        'Spalte3','Spalte4' | %{  
            $line.$_ = $line.$_ -replace '\.',','  
        }
    }
    $csv | export-csv $dst -Delimiter ";" -NoTypeInformation -Encoding UTF8 -Append  
}

Mein obiger Versuch ([datetime]::ParseExact()) ist eigentlich Quatsch, zu der Erkenntnis bin ich schon gekommen. Quatsch aus zwei Gründen: dadurch habe ich nicht das eigentlich gewollte Format und es funktioniert obendrein nicht
Weil da der dritte Culture-Parameter fehlt und natürlich die Property auch noch nicht existiert da nur reiner Text face-wink.

Für den Code oben sähe das mit [datetime]::ParseExact aber so aus falls es interessiert
$line.Spalte1 = [datetime]::ParseExact($line.Spalte1,'yyyy-MM-dd-HH:mm:ss',[cultureinfo]$null).toString('yyyy-MM-dd HH:mm:ss')  
em-pie
em-pie 15.08.2022 aktualisiert um 13:50:36 Uhr
Goto Top
'n Träumchen, @3479126418

Exakt so ausreichend. Habe es auf unsere CSV adaptiert und nun läuft es.

Besten Dank (auch für die Erklärung mit dem ...ParseExact()).