Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[Java] Log categorizen a.d.h.v. regular expressions

Pagina: 1
Acties:

  • TFBlunt
  • Registratie: November 2010
  • Laatst online: 19-10 16:11
Beste Tweakers,

Als onderdeel van mijn onderzoek probeer ik de elementen van een serverlog per regel te categorizeren. Het leek me een goed idee om hiervoor een stukje Java te schrijven. Het probleem is dat niet elke regel even lang is of dezelfde elementen bevat, dus simpelweg de Scanner klasse toepassen is geen optie. Nu heb ik wat gegoogled en kwam ik de Pattern en Matcher klassen tegen. Hiermee kan ik a.d.h.v een regular expression nagaan of die regel een van de elementen die ik zoek bevat.

Allemaal leuk en aardig, alleen loop ik tijdens de toepassing tegen een (voor mij) bijzonder probleem aan. Als voorbeeld neem ik het IP adres. Zodra ik een regel uit de log lees (het IP adres komt op deze regel voor), wordt deze niet gematcht a.d.h.v. het patroon. Bijzonder is hierbij dat, wanneer ik de String rechtstreeks (dus letterlijk in de code geplakt) evalueer, zonder deze eerst uit het bestand te lezen, deze wel matcht. Het onderstaande stukje code illustreert mijn probleem:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static final String IPV4_PATTERN = "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\b";

public static void convert(BufferedReader in, BufferedWriter out){
        Pattern ip = Pattern.compile(IPV4_PATTERN);
        try {
            while(in.ready()){
                                Row r = new Row();
                String line = in.readLine();
                Matcher m = ip.matcher(line);
                r.setIP(m.group());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


Aangezien line geen match heeft met IPV4_PATTERN gooit m.group() een exception. Vervang line echter met "0.0.0.0" of enig ander IP adres en de code werkt. Hebben jullie enig idee wat hier gebeurt? Alvast bedankt voor jullie hulp!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
Al eens geprobeerd zonder die \b?

https://niels.nu


  • pedorus
  • Registratie: Januari 2008
  • Niet online
Met debugger op regel 8 een breakpoint zetten, en kijken wat er in de variabele line zit (let ook op een mogelijke \r op het einde).

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


  • TFBlunt
  • Registratie: November 2010
  • Laatst online: 19-10 16:11
@Hydra
Jep, dat maakt voor het resultaat geen verschil. Ik heb die \b erbij gezet omdat in de log nog extra text volgt na het IP adres.

@Pedorus
Na het IP adres volgt nog een reeks tekst met andere gegevens. In de test die goed verloopt heb ik ook extra text achter het IP adres gezet en dit evalueert nog steeds naar true. In de debugger zie ik precies de tekst die ik verwacht (deze kan ik wegens vertrouwelijke informatie niet met je delen), zonder \r.

Kan het te maken hebben met hoe de tekst uit het log gelezen wordt door de reader?

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Lijkt me een sterk verhaal. Een string is een string, maakt niet uit hoe je eraan komt. Waarschijnlijk is er ergens een regel zonder ip adres, en break je niet on exception. Als ik snel kijk zie ik trouwens dat de code in de TS waarschijnlijk sowieso niet compileert (while {...} catch).

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
Euh, maar als je als regel "192.168.10.251 bla bla test" invoert dan werkt het toch ook niet? In je regex geef je niet aan dat er na dat IP-adres nog meer meuk komt.

https://niels.nu


  • TFBlunt
  • Registratie: November 2010
  • Laatst online: 19-10 16:11
Ik heb inderdaad een knipsel van mijn code gemaakt (omdat ik hier een kort voorbeeld wilde schetsen) en ik zie dat deze niet helemaal klopt. Het illustreert echter wel mijn probleem. Ik zal proberen het nog iets te verduidelijken:

Java:
1
2
3
4
5
public static final String IPV4_PATTERN = "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\b"; 


Matcher m = Pattern.compile(IPV4_PATTERN).matcher("0.0.0.0 - overige info");
m.find();


m.find() zoekt naar tekst in de gegeven string die voldoet aan het vooraf gegeven patroon. In dit geval levert de methode true op.

Java:
1
2
3
4
5
6
BufferedReader in = new BufferedReader(new FileReader("file.log"));
while(in.ready()){
   String line = in.read()
   Matcher m = Pattern.compile(IPV4_PATTERN).matcher(line);
   m.find();
}


In dit geval evalueert m.find() naar false, ook in dit specifieke voorbeeld. In de debugger heeft line dan de waarde "0.0.0.0 - overige info". Overigens doet de eerste fout zich al voor op de eerste regel van het log. Daar staat een IP adres, dat heb ik gecheckt ;)

  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
Als je aan het eind van die regex .+ (alles) toevoegt werkt 't wel. Gebruik eens m.matches() i.p.v. m.find()?

[ Voor 23% gewijzigd door Hydra op 13-03-2014 15:58 ]

https://niels.nu


  • TFBlunt
  • Registratie: November 2010
  • Laatst online: 19-10 16:11
.+ toevoegen geeft me in de 'lees case' nog steeds dezeflde exception. Dit is echter ook geen oplossing omdat de volgende stap (het ophalen van het IP adres d.m.v. m.group()) nu ook de rest van de string meeneemt. Dus in plaats van 0.0.0.0 is nu het resultaat 0.0.0.0 - overige info.

matches() levert me inclusief .+ true op, zonder .+ false. Dit betekent dan toch dat mijn patroon voor het IP adres wel klopt?

[ Voor 17% gewijzigd door TFBlunt op 13-03-2014 16:10 ]


  • Hydra
  • Registratie: September 2000
  • Laatst online: 06-10 13:59
TFBlunt schreef op donderdag 13 maart 2014 @ 16:06:
.+ toevoegen geeft me in de 'lees case' nog steeds dezeflde exception.
Ik heb je code vrijwel zonder aanpassingen overgenomen en mij bij krijg ik geen exception.
Dit is echter ook geen oplossing omdat de volgende stap (het ophalen van het IP adres d.m.v. m.group()) nu ook de rest van de string meeneemt. Dus in plaats van 0.0.0.0 is nu het resultaat 0.0.0.0 - overige info.
Ja moet ook goed kijken naar je match groepen: je hebt er 4 gedefinieerd (elk getal in het IP adres). De nulde groep is de hele gematchte string.
matches() levert me inclusief .+ true op, zonder .+ false. Dit betekent dan toch dat mijn patroon voor het IP adres wel klopt?
Ik weet niet precies wat find doet. Wat ik wel weet is dat dit gewoon werkt:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    public static final String IPV4_PATTERN = "(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5]))\\b.+";

    public static void convert(BufferedReader in, BufferedWriter out){ 
        Pattern ip = Pattern.compile(IPV4_PATTERN); 
        try { 
            while(in.ready()) { 
                String line = in.readLine();
                Matcher m = ip.matcher(line);
                if(m.matches())
                    System.out.println(m.group(1));
                else
                    System.out.println("No match");
            }
        }
        catch (IOException e) { 
            e.printStackTrace(); 
        } 

https://niels.nu


  • TFBlunt
  • Registratie: November 2010
  • Laatst online: 19-10 16:11
Find checkt of een gedeelte van de gegeven string aan het patroon voldoet, i.p.v. de gehele string. In ieder geval wel bedankt! Ik heb je code overgenomen, matches() vervangen door find() en de .+ uit het patroon gehaald. Het blijkt dat het nodig is om éérst find() aan te roepen voordat group() aangeroepen kan worden.

Het resultaat ziet er nu dus als volgt uit:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static final String IPV4_PATTERN = "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\b";

public static void convert(BufferedReader in, BufferedWriter out){
        Pattern ip = Pattern.compile(IPV4_PATTERN);  
        try {  
            while(in.ready()) {  
                Row r = new Row();
                String line = in.readLine(); 
                Matcher m = ip.matcher(line); 
                if(m.find()){ 
                    r.setIP(m.group());
                }
            } 
        } 
        catch (IOException e) {  
            e.printStackTrace();  
        }
}


r.getIP() levert nu 0.0.0.0 op, precies wat ik wilde! Nogmaals bedankt :) Nu verder puzzelen aan de andere logelementen..

  • drm
  • Registratie: Februari 2001
  • Laatst online: 09-06 13:31

drm

f0pc0dert

Dit is trouwens wel echt typisch een Perl klusje. Maar daar heb je niet direct iets aan :)

Music is the pleasure the human mind experiences from counting without being aware that it is counting
~ Gottfried Leibniz

Pagina: 1