2017-07-01 1 views
-1

Ich habe diese mehrzeiligen Protokolldatei:Spiel jede Nachricht in einer mehrzeiligen Protokolldatei mit regex

INFO 2017-07-01 12:01:56,987 [Thread-1] Class1:15 This is the message 1 
DEBUG 2017-07-01 12:01:56,987 [Thread-1] Class2:15 This is the message 2 
    that is multiline! 
WARN 2017-07-01 12:01:56,987 [Thread-1] Class3:15 This is a warn message 
ERROR 2017-07-01 12:01:56,987 [Thread-1] Class4:15 This is an error with the stacktrace... 
my.packkageName.MyException: exception! 
    at my.packkageName.Class4.process(Class4.java:11) 
    at ... 
INFO 2017-07-01 12:01:56,987 [Thread-1] Class1:15 This is another INFO message 

Ich mag einen regulären Ausdruck, dass jede einzelne Meldung im Protokoll, auf diese Weise übereinstimmt:

group 1: INFO 2017-07-01 12:01:56,987 [Thread-1] Class1:15 This is the message 1 

group 2: DEBUG 2017-07-01 12:01:56,987 [Thread-1] Class2:15 This is the message 2 
    that is multiline! 

group 3: WARN 2017-07-01 12:01:56,987 [Thread-1] Class3:15 This is a warn message 

group 4: ERROR 2017-07-01 12:01:56,987 [Thread-1] Class4:15 This is an error with the stacktrace... 
my.packkageName.MyException: exception! 
    at my.packkageName.Class4.process(Class4.java:11) 
    at ... 

Diese Regex ist nur für Single-Line-Nachrichten:

(?:ERROR|DEBUG|INFO|WARN).++ 
+0

Haben Sie Pattern.MULTILINE oder (? M) hinzugefügt. Diese Option wird am Anfang und am Ende jeder Zeile abgeglichen (andernfalls ist die Übereinstimmung am Anfang/Ende der Zeichenfolge). – fg78nc

+0

Zeile für Zeile lesen, und während eine Zeile nicht mit einem dieser Werte beginnt, wird sie an den aktuellen Datensatz angehängt, andernfalls fügen Sie den Eintrag hinzu, um einen neuen zu beginnen. Wenn das Protokoll klein ist und Sie es in den Speicher laden, können Sie "split" (? M)^(? = ERROR | DEBUG | INFO | WARN) ") –

+0

@ fg78nc ja, ich teste es auf regex101, mit Multiline-Option –

Antwort

0

Ich habe die Lösung gefunden.

Die Regex verwendet werden, ist das folgende:

/(?:DEBUG|INFO|ERROR|WARN)[\s\S]+?(?=DEBUG|INFO|WARN|ERROR)/gm 

Dieses Spiel jeder "Protokollmeldung", die zwischen den Worten DEBUG, INFO, ERROR oder WARN, in mehrzeiligen Weise enthalten ist.

+0

Dies ist ein Regex, der die richtigen Übereinstimmungen für Sie bei einem Online-Regex-Tester hervorhebt. Sobald Sie jedoch mit 'Matcher # find()' beginnen, werden Sie feststellen, dass das Programm zu langsam ist. Oder es stürzt ab. Oder die Übereinstimmungen sind nicht wie erwartet, da "DEBUG" irgendwo in einer Nachricht erscheint. Oder die Datei ist zu groß, um sie in den Speicher zu laden. Wir meinen es so, lesen Sie die Datei Zeile für Zeile. Regex zu beherrschen bedeutet zu wissen, wann man es benutzt und wann nicht. –

0

Um die Logdatei in eine Zeichenfolge zu laden und regex zu verwenden, um die Nachrichten zu finden, ist dies wahrscheinlich nicht die effizienteste Methode, große Logdateien zu verarbeiten.

Aber wenn Sie gut mit regex und wollen auch dann die letzte Meldung bekommen Sie so etwas tun könnten:

String logstr = "INFO 2017-07-01 12:01:56,987 [Thread-1] Class1:15 This is the message 1\n" 
+ "DEBUG 2017-07-01 12:01:56,987 [Thread-1] Class2:15 This is the message 2 \n" 
+ " that is multiline!\n" 
+ "WARN 2017-07-01 12:01:56,987 [Thread-1] Class3:15 This is a warn message\n" 
+ "ERROR 2017-07-01 12:01:56,987 [Thread-1] Class4:15 This is an error with the stacktrace...\n" 
+ "my.packkageName.MyException: exception!\n" 
+ " at my.packkageName.Class4.process(Class4.java:11)\n" 
+ " at ...\n" 
+ "INFO 2017-07-01 12:01:56,987 [Thread-1] Class1:15 This is another INFO message "; 

final Pattern pattern = Pattern.compile("^([A-Z]{4,}).+?(?=(?:^[A-Z]{4}|\\z))", Pattern.DOTALL | Pattern.MULTILINE); 
Matcher messages = pattern.matcher(logstr); 

while (messages.find()) { 
    System.out.println("---"+ messages.group(1));  
    System.out.println(messages.group(0)); 
} 

Wegen des Pattern.DOTALL der .* paßt auch die Linie Terminator.

Und mit der Pattern.MULTILINE passt die ^ auch nach jedem Leitungsabschluss außer am Ende des Eingangs.

Die \z markiert das Ende des Eingangs.