2017-09-07 1 views
0

Ich habe mehrere große Protokolldateien, die ich in CSV exportieren möchte. Zunächst möchte ich zwei Teile teilen, Datum und Ereignis. Das Problem, das ich habe, ist, dass nicht jede Zeile mit einem Datum beginnt.Parsen Sie mehrere Textzeilen mit Powershell und Export nach CSV

Hier ist ein Beispiel für ein Stück Protokoll. Datum/Uhrzeit sind immer 23 Zeichen. Der Rest variiert mit dem Protokoll und der Ereignisbeschreibung.

enter image description here

würde ich das Endergebnis gefällt, wie diese in Excel zu suchen.

enter image description here

Hier ist, was ich bisher ausprobiert habe, gibt aber nur die ersten 23 Zeichen jeder Zeile.

$content = Get-Content myfile.log -TotalCount 50 
for($i = 0; $i -lt $content.Length; $i++) { 
$a = $content[$i].ToCharArray() 
$b = ([string]$a[0..23]).replace(" ","") 
Write-Host $b } 
+2

könnten Sie einen Teil des Login-Text hinterlassen bitte, so kann ich etwas versuchen – ArcSet

+0

2017.09.04 12: 31: 11,343 \t Allgemeine \t BOECD :: PROCESS: Wort: Länge 3 [0917 1204 3029] Hex: Länge 6 [17 09 04 12 29 30] . \t Anzeige: False \t 2017.09.04 12: 31: 11,479 \t Allgemeine \t MelsecIoWrapper: beendet Scan: Gerät: 1, Scanstart: 2017.09.04 12.31.10 \t Anzeige: False \t 2017-09 -04 12: 31: 11.705 \t Allgemein \t BOODC :: ProcessEndTime: Wort: Länge 3 [0917 1204 0931] Hex: Länge 6 [17 09 04 12 31 09] . \t Anzeige: False \t 2017-09-04 12: 31: 13.082 \t Allgemein \t BOODC :: DV Daten: –

+0

Hinweis: In der eigentlichen Protokolldatei beginnt das Datum immer eine Zeile wie das Bild oben. Als ich das Sample eingefügt habe, hat es einfach alles zusammengepackt. –

Antwort

2

Lesen Sie die Datei in rohen als String mehrzeiligen, dann RegEx verwenden zum Zeitpunkt Muster aufgeteilt und für jeden Chunk machen ein benutzerdefiniertes Objekt mit den beiden Eigenschaften, die Sie wollen, wo der erste Wert die ersten 23 Zeichen, und der zweite Wert ist der Rest der Zeichenfolge getrimmt.

(Get-Content C:\Path\To\File.csv -Raw) -split '(?m)(?=^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})'| 
    Where{$_}| 
    ForEach-Object{ 
     [PSCustomObject]@{ 
      'Col1'=$_.Substring(0,23) 
      'Col2'=$_.Substring(23).Trim() 
     } 
    } 

Dann können Sie das zu einer CSV-Pipeline oder tun was immer Sie wollen mit den Daten. Wenn die Dateien wirklich massiv sind, ist das vielleicht nicht machbar, aber es sollte bei Dateien funktionieren, die bis zu ein paar hundert MB groß sind. Verwenden des Beispieltext, den Ausgang:

 
Col1     Col2 
----     ---- 
2017-09-04 12:31:11.343 General BOECD:: ProcessStartTime: ... 
2017-09-04 12:31:11.479 General MelsecIoWrapper: Scan ended: device: 1, ScanStart: 9/4/2017 12:31:10 PM Display: False 
2017-09-04 12:31:11.705 General BOECD:: ProcessEndTime: ... 
2017-09-04 12:31:13.082 General BOECD:: DV Data: 

... Die am Ende der beiden Leitungen sind, wo sie den mehrzeiligen Wert, um es auf dem Bildschirm angezeigt wird abgeschnitten, aber der Wert ist es intakt.

(?=...) ist eine sogenannte "positive Lookahead Assertion". Solche Assertionen bewirken, dass ein regulärer Ausdruck mit dem angegebenen Muster übereinstimmt, ohne ihn tatsächlich in die zurückgegebene Übereinstimmung/Zeichenfolge aufzunehmen. In diesem Fall gibt die Übereinstimmung die leere Zeichenfolge vor einem Zeitstempel zurück, sodass die Zeichenfolge dort aufgeteilt werden kann, ohne den Zeitstempel zu entfernen.

+1

Ich würde das Muster '(? M) (? =^\ D {4} -...) machen, um Zeitstempel am Anfang einer Zeile spezifisch zu entsprechen. Die Bindestriche und Doppelpunkte müssen nicht entkernt werden, BTW. –

+1

Danke, es fällt mir schwer, mich daran zu erinnern, was alles als reservierter Charakter in RegEx gilt, daher tendiere ich manchmal dazu, überzulaufen. Ich habe auch die Antwort aktualisiert, um Ihren Vorschlag zu reflektieren, nur Datum/Zeiten am Anfang einer Zeile zu bekommen, das ist eine ausgezeichnete Idee. – TheMadTechnician