# parsen mit regex -> ein schnelles Ende



## MiMa (5. Okt 2016)

gestern habe ich mich entschieden mein parsing der ISBN Erkennung nicht mit meiner 2 Jahre alten Methode weiter zu entwicklen. Bei der alten Methode habe ich mittles Strig suche und Manipulation die ISBN ziemlich aufwending mit langen Code und und allen eventualitäten programmiert. Auch musste ich vieles in Abfangen und arbeitet trotzdem nicht alle Dokumente durch.

Nun habe ich eine wesentlich kleinere Methode mit regex geschrieben, die mir auch eleganter und kürzer erscheint. Nach vier Überprüfungen blieb es stehen??
Der Grund dafür war eine richtige (geprüfte) ISBN, die aber nicht in der Datenbak gelistet (e-ISBN) war. Eine entsprechende Abfangungsmethode werde ich implemetieren, aber es gibt in der Datei noch eine weitere ISBN, die wohl in der Datenbank gelistet ist.

Das suchen mit rexeg Pattern und Matcher liefert ein Ergebnis in der Gruppe(0) zurück und teilbereiche in den anderen Gruppe(1-...).
Weis jemand ob es bei dieser Art der Abfrage, Paramter gibt, indem man mehrere Totale Ergebnisse erhält? Oder muss man diese Abfrage in einer Schleife auf den String ausführen lassen um dann mehrere Ergebnisse in einer Liste zu speichern?
Danke


----------



## VfL_Freak (5. Okt 2016)

Moin,
ich bin mir nicht sehr sicher, ob ich Deine Frage verstehe ... 

Du hast also _*n*_ ISBNs, die geparst werden sollen, richtig?
Dann solltest Du auch in einer Schleife über diese _*n*_ Werte laufen und jeden einzeln parsen!



> Das suchen mit rexeg Pattern und Matcher liefert ein Ergebnis in der Gruppe(0) zurück und teilbereiche in den anderen Gruppe(1-...).
> Weis jemand ob es bei dieser Art der Abfrage, Paramter gibt, indem man mehrere Totale Ergebnisse erhält?


Was genau meinst Du damit ?? 

Gruß Klaus


----------



## MiMa (5. Okt 2016)

Die Gruppen die ich meine habe ich als Kommentar im Code gekennzeichnet.

```
// ISBN: 978-3-8266-8674-0
        // Full match   `978-3-8266-8674-0`
        // Group 1.     `978`   Buchcode
        // Group 2.     `3`     Ländercode
        // Group 3.     `8266`  Verlagscode
        // Group 4.     `8674`  Titelcode
        // Group 5.    `0`     Prüfziffer
        String isbnMuster = "(97+[8-9]{1,1})+[-]+([0-9]{1,5})+[-]+([0-9]{2,7})+[-]+([0-9]{2,4})+[-]+([0-9]{1,1})";

        // Suchmuster für ISBN 10, 13 definieren
        Pattern muster = Pattern.compile(isbnMuster);

        // Wendet das Suchmuster auf den String an
        Matcher gefunden = muster.matcher(textInhalt);

        while (gefunden.find()) {
            log.info("Die gefundene ISBN ist            : " + gefunden.group(0));
            gefundeneIsbn = gefunden.group(0);
//            // Ausgabe der Gruppen von Buchcode bis Prfziffer
//            for (int i = 1; i <= gefunden.groupCount(); i++) {
//                System.out.println("gefundene ISBN Gruppe " + i + " : " + gefunden.group(i));
```
Die Ausgabe der anderen Gruppen(1-5) interessieren mich derzeit nicht und habe diese deshalb auskommentiert. Das gefundene Muster wird scheinbar nur in Group(0) gespeichert und dann der Suchvorgang beenden?
Da ich mit Regular Expressions kaum Erfahrung habe, würde ich gerne wissen, wie ich "n" weitere ISBN Nummern abfragen kann?
Bevor ich jetzt wieder Monstercode mit vielen Schleifen baue, möchte ich mal nachfragen, ob es in regEx bestimmte Funktionen dafür gibt?
Danke


----------



## VfL_Freak (5. Okt 2016)

Habe gerade mal nach "Regex ISBN" gegoogelt und einige für interessante Links gefunden:
http://howtodoinjava.com/regex/java-regex-validate-international-standard-book-number-isbns/
http://regexlib.com/Search.aspx?k=isbn&AspxAutoDetectCookieSupport=1
https://www.safaribooksonline.com/l...pressions-cookbook/9781449327453/ch04s13.html

Vor allem der erste könnte für Dich interessant sein ...

Gruß Klaus


----------



## MiMa (5. Okt 2016)

Danke Dir.
Ich hatte auch mit Google einiges gefunden, aber die Monsterzeichenketten funktionierten im Online Regex tester nicht. Noch nicht mal mit den darunter angegebenen Muster, die gefunden werden müssten.
Oder ich bin zu d... dafür. 
Mein regex Suchstring sieht jetzt auch wieder anders aus als oben und wird im tester von meinen ISBNs gefunden.
Ich befürchte das,

```
// Wendet das Suchmuster auf den String an
        Matcher gefunden = muster.matcher(textInhalt);
```
sucht und wenn etwas gefunden wurde ist die suche beendet?
Würde das bedeuten, das diese funktion mehrmals auf den Text angewendet werden muss und die gefundenen Werte in eine arrayList zu speichern, aber keine doppelten, sonst endlosschleife...?
Oder gibt es dafür spezielle Funktionen?

Für diejenigen die auch einsteigen wollen, super erklärt
https://danielfett.de/de/tutorials/tutorial-regulare-ausdrucke/


----------



## MiMa (5. Okt 2016)

Habe zwar gefunden was ich gesucht hatte, jedenfalls ist es mir nicht sofort aufgefallen.

```
System.out.println("Die gefundene ISBN ist : " + gefunden.group(0));
```
ergibt folgende Ausgabe in der Konsole.


> Die gefundene ISBN ist : 978-3-540-76393-2
> Die gefundene ISBN ist : 978-3-540-76394-9
> Die gefundene ISBN ist : 978-3-540-76394-9


Ich komme zu dem Schluss, das doch der gesamte Text durchsucht wird und alle zutreffenden Ergebnisse eingesamtelt werden. Ich vermute mal das in in Group(0) eine Liste mit den Ergebnissen enthalten ist.
Wie kann ich denn dann auf die einzelnen Ergebnisse zugreifen.

```
System.out.println("Die gefundene ISBN ist : " + gefunden.group(0).indexOf(0));
```
Habe dann versucht wie auf einem Array zu zu greifen aber hat nicht geklappt?

https://docs.oracle.com/javase/7/docs/api/java/util/regex/Matcher.html
Dort finde ich auch nicht wie ich auf den ersten, oder den letzten, oder nur auf den Mittleren zugreifen kann?


----------



## MiMa (7. Okt 2016)

Thema erledigt, habe eine Lösung gefunden.


----------



## VfL_Freak (8. Okt 2016)

aha, und warum postest Du dann die Lösung hier nicht?? 
Ist doch für alle, die ein ähnliches Problem haben, interessant !!

Gruß Klaus


----------



## MiMa (8. Okt 2016)

Nach langen lesen und probieren, habe ich festgestellt, das man die Ergebnisse aus "gefunden.proup()" nicht abfragen kann, da es KEINE Strings sind. Das hat mich lange Zeit beschäftigt, da ich immer angenommen hatte das Strings als Ergebnisse zurückgegeben werden, da diese so aussahen.
Im Buch habe ich dann nachgelesen, das group() nur eine Liste von Objekten mit Anfangs -und Enpositionen zu den gefundem Muster enthält. Daher kann man weder Stringoperationen noch ArrayList funktionen darauf anwenden.

```
System.out.println("Die gefundene ISBN ist : " + gefunden.group(0));
```
Mit dieser einen Ausgabezeile wird das erste Ergebnis auf den Bildschirm ausgegeben, von der Anfangs -und Endposition, das wars.

```
while (gefunden.find()) {
            System.out.println("Die gefundene ISBN ist : " + gefunden.group(0));
}
```
In der Schleife werden alle Ergebnisse nacheinander ausgegeben solange "gefunden.find()" true zurückmeldet.
Da ich nun keine Strings zum verarbeiten hatte, nahm ich das zurückgegebene Ergebnis und steckte es in eine String Array Liste. Bei jedem durchlauf der Schelife wurde dann das nächste Ergebnis zurückgeliefert, welches ich dann jeweils an sie ArrayListe angehangen habe.
Beim austritt der While Schleife hatte ich dann eine Array Liste mit Strings, die ich dann weiter verarbeiten kann.

```
// Schleife der gefundenen Einträge abarbeiten
        while (gefunden.find()) {          
            // prüfen der ISBN Nummer auf Korrektheit
            boolean isbnPruefung = pruefeISBN(gefunden.group());
            if (isbnPruefung == true) {
                // Die ISBN wird der Liste hinzugefügt
                isbnListe.add(gefunden.group());
                System.out.println("Die geprüfte ISBN-Nummer ist korrekt, wurde zur Liste hinzugegügt.");
            } else {
                System.out.println("Die geprüfte ISBN ist nicht korrekt und wurde NICHT hinzugefügt");
            }
}
```

Damit die Liste dann auch keine doppelten ISBN Nummerns enthält habe ich mir überlegt, vor dem hinzufügen zur Liste noch zu überprüfen ob die Nummer die hinzugefügt werden soll, bereits in der Liste enthalten ist. Wenn nein, dann hinzufügen, ansonsten ignorieren.

Vorher hatte ich regex, Matcher und Patterns noch nicht gearbeitet und kann sagen, das es ziemlich komplex ist und nicht immer das zu sein scheint, wonach es aussieht.


----------



## mrBrown (8. Okt 2016)

MiMa hat gesagt.:


> Nach langen lesen und probieren, habe ich festgestellt, das man die Ergebnisse aus "gefunden.proup()" nicht abfragen kann, da es KEINE Strings sind. Das hat mich lange Zeit beschäftigt, da ich immer angenommen hatte das Strings als Ergebnisse zurückgegeben werden, da diese so aussahen.
> Im Buch habe ich dann nachgelesen, das group() nur eine Liste von Objekten mit Anfangs -und Enpositionen zu den gefundem Muster enthält. Daher kann man weder Stringoperationen noch ArrayList funktionen darauf anwenden.


Das klingt ehrlich gesagt sehr verwirrt...ein Blick ins JavaDoc hätte gereicht, um zu sehen das Matcher.group sehr wohl einen String zurück gibt...


----------



## MiMa (8. Okt 2016)

Vielleicht habe ich mich schlecht ausgedrückt und verwirrt hat es mich auch.
Es werden lediglich Positionsangaben ANFANG bis ENDE aus dem Textinhalt durch das Suchmuster als Ergebnis zurückgegeben. Man kann also schon einen Textinhalt entnehmen indem man dann sagt entnehme mir den Text von ANFANG bis ENDE heraus. Um es nicht so ausführlich machen zu müssen gibt es eine Vereinfachnung und zwar die Rückgabe mit der Methode "group()" diese Methode macht dies und gibt einen String zurück. Aber diese Strings (mehrzahl) konnte ich nach der Ausführung nirgendwo ansprechen ausser in der While Schleife. Ich hatte die Schwierigkeit zu begreifen, da sind Strings, wie spreche ich diese nach der Ausführung an?? Gar nicht. Es muss während der Ausführung sein.


----------

