Aufteilung einer Logdatei anhand bestimmter Zeichenkette
Hallo!
Ich habe jetzt schon eine Weile gesucht aber bisher noch keine passende Lösung gefunden, ich hoffe, Ihr könnt mir helfen!
Eine Fachsoftware erzeugt bei Abarbeitung mehrerer gleichartigere Jobs eine zusammenhängende Logdatei. Es ist leider nicht möglich, für jeden Job eine eigene Log zu erstellen.
Die als *.log vorliegende Textdatei soll ich in eine auswertbare Excel-Tabelle umwandeln. Teilweise werden Daten für alle Datensätze der Excel-Tabelle nur aus der Überschrift der Log geholt. Die Log-Datei hat ungefähr folgende Struktur:
Im Beispiel besteht die Log-Datei aus zwei Jobs, es können aber auch erheblich mehr sein. Für jeden Job soll eine eigene Excel-Tabelle erstellt werden, da die Daten aus den Zeilen 5 und 6 in die Spalten der einzelnen betroffenen Namen eingefügt werden sollen.
Da ich jeweils nie weiß, wieviele betroffene Namen vorhanden sind, kann ich nicht einfach sagen: "Starte den Import dieses Mal in Zeile xxx." Es sind teilweise über 1000 Namen betroffen.
Ich nehme an, es würde am meisten Sinn machen, vor der Verarbeitung via Excel-Makro die Text-Datei per Batch in mehrere einzelne Text-Dateien aufzusplitten. Ich habe leider nur sehr rudimentäre Erfahrungen in Batch-Programmierung und vor allem zwei Fragen stehen nun im Raum.
1. Wie trenne ich die Datei jeweils an den Stellen zwischen den Rauten-Linien
2. Wie speichere ich die einzelnen Teile unter einem möglichst aussagekräftigen Namen (am Besten dem aus Zeile 5 des jeweiligen Jobs)
Ich hoffe, meine Fragestellung ist einigermaßen klar und nicht zu verworren. Ich sitze da jetzt schon ewig vor und das Hirn überhitzt langsam...
Ich habe jetzt schon eine Weile gesucht aber bisher noch keine passende Lösung gefunden, ich hoffe, Ihr könnt mir helfen!
Eine Fachsoftware erzeugt bei Abarbeitung mehrerer gleichartigere Jobs eine zusammenhängende Logdatei. Es ist leider nicht möglich, für jeden Job eine eigene Log zu erstellen.
Die als *.log vorliegende Textdatei soll ich in eine auswertbare Excel-Tabelle umwandeln. Teilweise werden Daten für alle Datensätze der Excel-Tabelle nur aus der Überschrift der Log geholt. Die Log-Datei hat ungefähr folgende Struktur:
20180813 14:06 || VeraenderungDatenJob || ##########################
20180813 14:06 || VeraenderungDatenJob || Starte Job "VeraenderungDatenJob".
20180813 14:06 || VeraenderungDatenJob || ##########################
20180813 14:06 || VeraenderungDatenJob || Die Daten XY werden durch die Daten YZ ersetzt:
20180813 14:06 || VeraenderungDatenJob || NameYZ
20180813 14:06 || VeraenderungDatenJob || YZ hat die Telefonnummer: 123456789
20180813 14:06 || VeraenderungDatenJob || Folgende Personen sind hiervon betroffen
20180813 14:06 || VeraenderungDatenJob || Name: Karl Koch
20180813 14:06 || VeraenderungDatenJob || Name: Liese Müller
20180813 14:06 || VeraenderungDatenJob || Name: Willi Wuppel
...
20180813 14:06 || VeraenderungDatenJob || ##########################
20180813 14:06 || VeraenderungDatenJob || Der Job wurde erfolgreich beendet.
20180813 14:06 || VeraenderungDatenJob || ##########################
20180813 14:06 || VeraenderungDatenJob || ##########################
20180813 14:06 || VeraenderungDatenJob || Starte Job "VeraenderungDatenJob".
20180813 14:06 || VeraenderungDatenJob || ##########################
20180813 14:06 || VeraenderungDatenJob || Die Daten ÄÖ werden durch die Daten BC ersetzt:
20180813 14:06 || VeraenderungDatenJob || NameBC
20180813 14:06 || VeraenderungDatenJob || BC hat die Telefonnummer: 987654321
20180813 14:06 || VeraenderungDatenJob || Folgende Personen sind hiervon betroffen
20180813 14:06 || VeraenderungDatenJob || Name: Hansi Hoppel
20180813 14:06 || VeraenderungDatenJob || Name: Erna P.
20180813 14:06 || VeraenderungDatenJob || Name: Helga Husten
...
20180813 14:06 || VeraenderungDatenJob || ##########################
20180813 14:06 || VeraenderungDatenJob || Der Job wurde erfolgreich beendet.
20180813 14:06 || VeraenderungDatenJob || ##########################
Im Beispiel besteht die Log-Datei aus zwei Jobs, es können aber auch erheblich mehr sein. Für jeden Job soll eine eigene Excel-Tabelle erstellt werden, da die Daten aus den Zeilen 5 und 6 in die Spalten der einzelnen betroffenen Namen eingefügt werden sollen.
Da ich jeweils nie weiß, wieviele betroffene Namen vorhanden sind, kann ich nicht einfach sagen: "Starte den Import dieses Mal in Zeile xxx." Es sind teilweise über 1000 Namen betroffen.
Ich nehme an, es würde am meisten Sinn machen, vor der Verarbeitung via Excel-Makro die Text-Datei per Batch in mehrere einzelne Text-Dateien aufzusplitten. Ich habe leider nur sehr rudimentäre Erfahrungen in Batch-Programmierung und vor allem zwei Fragen stehen nun im Raum.
1. Wie trenne ich die Datei jeweils an den Stellen zwischen den Rauten-Linien
2. Wie speichere ich die einzelnen Teile unter einem möglichst aussagekräftigen Namen (am Besten dem aus Zeile 5 des jeweiligen Jobs)
Ich hoffe, meine Fragestellung ist einigermaßen klar und nicht zu verworren. Ich sitze da jetzt schon ewig vor und das Hirn überhitzt langsam...
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 383909
Url: https://administrator.de/forum/aufteilung-einer-logdatei-anhand-bestimmter-zeichenkette-383909.html
Ausgedruckt am: 07.04.2025 um 12:04 Uhr
6 Kommentare
Neuester Kommentar
Weiß nicht wie das in cmd zu lösen wäre, aber mit PowerShell (ebenfalls bestandteil von Windows
) sollte es gehen
Glaube die Antwort auf beide Fragen ist: RegEx + paar Operatoren aus Powershell
#Inhalt des Logs einlesen, und der Variable InhaltRAW zuweisen
#Die lange Datei nach dem String "Der Job wurde erfolgreich beendet." aufteilen, das Ergebnis ist ein Array aus den einzelnen Abschnitten
#Die einzelnen Logs aus dem Array in einzelne, nummerierte Dateien Speichern:
PS: Du kannst ja noch nach einem besseren String zu trennen suchen wenn du magst - einfach alles hinter dem "?<=" ersetzen bis zu der schließenden klammer
MFG N-Dude
Edit:
Hier der richtige Schritt3, falls du die einzelnen Logs auch richtig benannt haben willst:
Glaube die Antwort auf beide Fragen ist: RegEx + paar Operatoren aus Powershell
#Inhalt des Logs einlesen, und der Variable InhaltRAW zuweisen
$InhaltRAW = Get-Content .\logdatei.log -Raw
#Die lange Datei nach dem String "Der Job wurde erfolgreich beendet." aufteilen, das Ergebnis ist ein Array aus den einzelnen Abschnitten
$ArrayOfLog = $InhaltRAW -split '(?<=Der Job wurde erfolgreich beendet.)'
#Die einzelnen Logs aus dem Array in einzelne, nummerierte Dateien Speichern:
$ArrayOfLog | ForEach-Object -Begin {$i=1} -Process {$_ > "log$i.txt"; $i++}
PS: Du kannst ja noch nach einem besseren String zu trennen suchen wenn du magst - einfach alles hinter dem "?<=" ersetzen bis zu der schließenden klammer
MFG N-Dude
Edit:
Hier der richtige Schritt3, falls du die einzelnen Logs auch richtig benannt haben willst:
$ArrayOfLog | ForEach-Object -Process {if ($_ -match '\bName\w{2}\b') {$Name = $Matches.Values; $_ > "$Name.txt"}}
Hallo BaseBubble,
ich habe hier mal ein Batchscript zum Zerlegen der Log-Datei in Einzeldateien zusammengeschrotet:
In Zeile 3 musst Du den Pfad zur Log-Datei eintragen und in Zeile 5 das Ausgabeverzeichnis (nur den Pfad, ohne abschließenden Backslash!)
Das Script extrahiert nur die Inhalte aus Spalte 4 des Logs und dürfte bei einer großen Log-Datei nicht sehr performant sein.
Die Dateien werden nach dem Inhalt von Zeile 5 jedes Jobs benannt. Sollten mehrere Jobs vorhanden sein, deren Zeile 5 identisch ist und somit zu gleichen Dateinamen führen würden, werden die Dateinamen mit Zählern versehen (
Ich gehe mal davon aus, dass die Log-Datei in der Zeichen-Codierung Windows-1252 (ANSI) gespeichert wurde. Aus diesem Grund habe ich dafür gesorgt (Zeile 13), dass die Datei auch mit dieser Codierung eingelesen wird. Das ist wichtig, damit die Ausgabedateien auch dann korrekte Namen erhalten, wenn in Zeile 5 der Job-Daten deutsche Umlaute vorkommen.
Grüße
Friemler
ich habe hier mal ein Batchscript zum Zerlegen der Log-Datei in Einzeldateien zusammengeschrotet:
@echo off & setlocal
set "InFile=.\Xyz.log"
set "TmpFile=%TEMP%\BlockData.txt"
set "OutFilePath=."
set "OutFile=%OutFilePath%\ThisIsAnError.txt"
set "StartBlock="
set "InBlock="
set "LineCnt="
chcp 1252 > NUL
del "%TmpFile%" 1>NUL 2>NUL
for /f "usebackq tokens=4 delims=|" %%a in ("%InFile%") do (
echo %%~a|findstr /ibr /c:" *Starte Job" > NUL && (
set "StartBlock=1"
set "InBlock="
set "LineCnt="
)
echo %%~a|findstr /ir /c:"^ *##*$" > NUL && (
if defined StartBlock (
set "StartBlock="
set "InBlock=1"
set "LineCnt="
) else (
set "InBlock="
set "LineCnt="
call :MoveFile
)
)
if defined InBlock (
if not defined LineCnt (
set /a LineCnt=0
) else (
set /a LineCnt+=1
call :ProcessLine "%%~a"
)
)
)
exit /b 0
:ProcessLine
for /f "tokens=*" %%z in ("%~1") do (
if "%LineCnt%" equ "2" (
set "OutFile=%OutFilePath%\%%~z.txt"
)
echo >>"%TmpFile%" %%~z
)
exit /b 0
:MoveFile
setlocal enabledelayedexpansion
set /a FileCnt=1
if exist "%OutFile%" (
for %%z in ("%OutFile%") do (
for %%y in ("%%~dpnz*%%~xz") do (
set /a FileCnt+=1
set "OutFile=%%~dpnz_(!FileCnt!)%%~xz"
)
)
)
move "%TmpFile%" "%OutFile%" 1>NUL 2>NUL
endlocal
exit /b 0
In Zeile 3 musst Du den Pfad zur Log-Datei eintragen und in Zeile 5 das Ausgabeverzeichnis (nur den Pfad, ohne abschließenden Backslash!)
Das Script extrahiert nur die Inhalte aus Spalte 4 des Logs und dürfte bei einer großen Log-Datei nicht sehr performant sein.
Die Dateien werden nach dem Inhalt von Zeile 5 jedes Jobs benannt. Sollten mehrere Jobs vorhanden sein, deren Zeile 5 identisch ist und somit zu gleichen Dateinamen führen würden, werden die Dateinamen mit Zählern versehen (
NameYZ.txt
, NameYZ_(2).txt
, NameYZ_(3).txt
, usw.).Ich gehe mal davon aus, dass die Log-Datei in der Zeichen-Codierung Windows-1252 (ANSI) gespeichert wurde. Aus diesem Grund habe ich dafür gesorgt (Zeile 13), dass die Datei auch mit dieser Codierung eingelesen wird. Das ist wichtig, damit die Ausgabedateien auch dann korrekte Namen erhalten, wenn in Zeile 5 der Job-Daten deutsche Umlaute vorkommen.
Grüße
Friemler
Hi,
ich habe mein Script oben angepasst, jetzt wird nur der Inhalt der Spalte 4 extrahiert. Gesteuert wird das über die
Außerdem habe ich das Script gegen das Überschreiben von Ausgabedateien mit gleichem Namen abgesichert und entsprechende Hinweise ergänzt.
Grüße
Friemler
ich habe mein Script oben angepasst, jetzt wird nur der Inhalt der Spalte 4 extrahiert. Gesteuert wird das über die
TOKENS
-Option der FOR
-Schleife. Siehe auch mein Tutorial zur FOR-Schleife.Außerdem habe ich das Script gegen das Überschreiben von Ausgabedateien mit gleichem Namen abgesichert und entsprechende Hinweise ergänzt.
Grüße
Friemler
Oder wenn du Plain Excel bevorzugst, hier als VBA zusammengeschrotet. Wie du das im Sheet aufgeteilt haben wolltest kann ich anhand deiner Beschreibung leider nicht ganz deuten, deshalb erst mal nur grundlegend auf Spalten verteilt.
Grüße Uwe
Sub ProcessLog()
Dim arrNames() As Variant, cnt As Long, fso As Object, rngOut As Range, regex As Object, blocks As Object, block As Object
' Pfad zur Logdatei
Const LOGFILE = "D:\Logfiles\MeinMegaLog.log"
'Objekte
Set fso = CreateObject("Scripting.FileSystemObject")
Set regex = CreateObject("vbscript.regexp")
' Regex Optionen festlegen
regex.Global = True: regex.IgnoreCase = True: regex.MultiLine = True
regex.Pattern = "Starte Job[\s\S]*?#{5,}[\r\n]+([\s\S]*?)[^\r\n]+#{5,}"
' Inhalt des Logs auslesen
strContent = fso.OpenTextFile(LOGFILE, 1).ReadAll()
' Ausgabe startet in dieser Zeile
Set rngOut = Range("A2")
' Überschriften setzen
With Range("A1:C1")
.Value = Array("Name", "Daten", "Namen")
.Font.Bold = True
End With
' Regex ausführen
Set blocks = regex.Execute(strContent)
' neuen Regex Pattern für die Namen festlegen
regex.Pattern = " \|\| Name:\s*(.*)"
' Für jeden Logabschnitt
For Each block In blocks
' Name und Daten auslesen
arrLines = Split(block.submatches(0), vbNewLine, -1)
strName = Trim(Split(arrLines(1), "||", 4, vbTextCompare)(3))
strDaten = Trim(Split(arrLines(2), "||", 4, vbTextCompare)(3))
' betroffene Namen auslesen und in Array schreiben
cnt = 1
Set matchedNames = regex.Execute(block.submatches(0))
For Each n In matchedNames
ReDim Preserve arrNames(1 To cnt)
arrNames(cnt) = Trim(n.submatches(0))
cnt = cnt + 1
Next
' Name und Daten ausgeben
rngOut.Resize(1, 2).Value = Array(strName, strDaten)
' betroffene Namen in Spalten ausgeben
rngOut.Offset(0, 2).Resize(1, UBound(arrNames)).Value = arrNames
' move output range to next line
Set rngOut = rngOut.Offset(1, 0)
Next
End Sub