Probleme mit RegEx

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von bomberman2910.

    Probleme mit RegEx

    Hallo,

    ich habe ein kleines Problem mit den regular expressions. Über die SuFu habe ich hier schon einen interessanten Beitrag gefunden gehabt, dieser hat mir aber nicht ausreichend weit geholfen.

    Und zwar habe ich folgendes Problem:
    Ich bin dabei eine HTML-Datei auseinanderzupflücken, um an bestimmte Informationen ranzukommen. Ich habe es inzwischen auch schon geschafft, den String, in dem sich die gesuchten Infos befinden, so weit einzugrenzen, dass ich bis auf ein paar Tags auch alles drumherum entfernt habe.
    Was noch übrig ist, sieht ziemlich genau so aus (ich habe lediglich die Infos entfernt):

    HTML-Quellcode

    1. <tr class='info'><td class='info' colspan="2"><b>benötigte Info</b></td></tr>
    2. <tr class='info'><td class='info' colspan="2"><b>benötigte Info</b></td></tr>
    3. <tr class='info'><td class='info' colspan="2"><b>benötigte Info</b></td></tr>

    Zu den Infos ist zu sagen, dass sie keinem bestimmten Schema folgen, sondern einfach nur Sätze von zufälliger Länge sind. Außerdem sind es nicht immer nur drei Info-Zeilen, sondern können durchaus auch mehr oder auch weniger sein.

    Meine erste Idee war es, den String solange zu zerteilen, bis ich alle Infos rausgeschnitten habe, bin dann aber zu dem Ergebnis gekommen, dass ich mich dabei dumm und dämlich schreibe und auch nicht auf die verschiedenen Anzahlen reagieren kann.

    Nachdem ich nun ein bisschen im Internet gesucht habe und auch hier die SuFu befragt habe, habe ich einen Beitrag gefunden, in dem ein ähnliches Problem gelöst wird, allerdings nur mit einmaligem Auftreten eines rauszusuchenden Strings. Dort wurde es mit RegEx.Match gelöst.

    Meine Frage ist nun, ob ich dies genauso tun kann, und wenn ja, wie sähe das Pattern dazu aus?

    Mfg bomberman2910

    P.S.: Mit diesem Befehl hat es schon mal nicht funktioniert:

    Visual Basic-Quellcode

    1. Regex.Match(vp_info_string_step1, "\<w\><info>\<\/w\>").Groups("info").ToString()
    Probier's damit:

    VB.NET-Quellcode

    1. "(?<=colspan=""\d+?""><b>).+?(?=</b></td></tr>)"

    Ohne Groups - Einfach den Wert des Matches auslesen.

    PS: Für mehrere Treffer nutze Regex.Matches
    Tipp: Wenn du Probleme haben solltest, dir Regex vorzustellen, kannst du mal dieses Seite ausprobieren: debuggex.com/ .Das ist bisher der einzige Online - Regex - Tester, der diese auch visualisieren kann. Vielleicht später bei komplexeren Ausdrücken praktisch.

    Nebenbei: Soweit ich weiß (korrigert mich einer sofern ich grad Mist schwafele) werden Gruppen mittels

    Quellcode

    1. (?<name>zeichenklasse)
    genutzt. Eventuell auch ein Grund, warum du keinen Treffer erhältst.

    Edit:
    Du kannst zum Beispiel wie folgt dein Ziel erreichen (das ist die "Bananenlösung", die reift noch nach, sprich kann noch ausgearbeitet werden ;)):

    Quellcode

    1. ​<tr class='info'><td.*><b>(?<info>.*)\<\/b\>\</td>
    Jetzt schnell und einfach das Zehnfingersystem mit Scribble 3 erlernen. Mehr Informationen und Download gibts hier. Redundancy2 - leichtgewichtige freie Cloudsoftware. Folge mir auf GitHub

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Fury“ ()

    Also irgendwie hat keine der bisher genannten Lösung zum Ziel geführt, aber trotzdem schon mal danke.

    Interessant fand ich das Ergebnis bei dem Pattern von Higlav, wo mir mein Programm dann als Match-Array zusammengesetzt "System.Text.RegularExpressions.MatchCollection" (oder so ähnlich) ausgibt. Die Idee mit den Groups muss ich auch verwerfen, weil .Groups() nicht zu Matches passt.

    Und zu deinem Tipp, Fury: Wenn ich auf der Seite zum Beispiel die erste Zeile meines Strings und dann dazu die verschiedenen Patterns (auch mit Abwandlungen) eingegeben habe, kam jedes Mal heraus, dass es keine Übereinstimmungen gäbe. Aber immerhin hilft die Seite beim Verständnis des Ganzen :)
    Gerade wenn du Gruppierungen benutzts, musst du bei der Auswahl (dort wo JavaScript steht) das letzte Auswählen. Sonst geht das nicht.
    Jetzt schnell und einfach das Zehnfingersystem mit Scribble 3 erlernen. Mehr Informationen und Download gibts hier. Redundancy2 - leichtgewichtige freie Cloudsoftware. Folge mir auf GitHub
    Hi,

    dein Problem ist insofern kompliziert, als dass im oben von dir angegebenen HTML-Code so ziemlich nichts "endeutiges" ist, an dem man ansetzen könnte, sprich es muss ein eindeutiger Ankerpunkt vorhanden sein, von dem aus man die Suche starten kann bis dahin wo der Text ist der gefunden werden soll. Im allgemeinsten Fall kann man auch <b>.*?<\/b> schreiben.
    Da aber nunmal nicht mehr gegeben ist, ist der einzig sinnvolle Pattern dieser:
    (?<=<tr +class\=\"info\".*?<td class\=\"info\"[^<>]+><b>).*?(?=<\/b>)
    Der Pattern findet somit genau die "benötigte Info". Die Zeichen davor und danach dienen zwar dazu, eben diese Informationen zu finden, letztendlich ist das Ergebnis aber nur der Text den du finden willst. In dem speziellen Fall mit dem Text von oben (die 3 Zeilen) kriegst du also in der Matchcollection 3 Elemente.
    Du arbeitest mit VB, das heißt du musst innerhalb des Pattern für jedes Anführungszeichen natürlich zwei davon hinschreiben (also "" statt ").
    Somit ergibt sich für VisualBasic der Pattern (?<=<tr +class\=\""info\"".*?<td class\=\""info\""[^<>]+><b>).*?(?=<\/b>)
    *Hinweis: habe den Pattern jetzt nicht getestet, ich vermute nur dass er funktioniert. Sollte er aber.

    Link :thumbup:
    Hello World
    Also mit dem Pattern von Link hats erst auch nicht funktioniert, bis ich gesehen habe, dass in dem ursprünlichen HTML-Code statt der doppelten, einfache Anführungszeichen benutzt werden. Jetzt funktioniert er auch :) Vielen Dank für die Hilfe :)

    Aber mal so nebenbei: Wieso ist da nichts eindeutig? Es ist doch eigentlich immer alles gleich, bis auf die Information zwischen den b-Tags. Habe ich jetzt das Prinzip noch nicht verstanden, dass das wirklich so viel ausmacht?
    Huhu,
    obwohl ich wirklich ein Freund von Regex bin, würde ich ab und zu auch die pragmatische Variante nehmen:

    VB.NET-Quellcode

    1. Dim strTest As String = "<tr class='info'><td class='info' colspan='2'><b>benötigte Info</b></td></tr>"
    2. Dim strInfo As String = Split(Split(strTest, "<tr class='info'><td class='info' colspan='2'><b>")(1), "</b></td></tr>")(0)
    3. 'strInfo ausgeben..

    Getestet -> geht.

    LG,
    Bruno

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „diylab“ ()

    bomberman2910 schrieb:

    Aber mal so nebenbei: Wieso ist da nichts eindeutig?

    Also damit meine ich folgendes: Du hast ja oben im Eingangspost 3 Zeilen hingeschrieben. Ich glaube allerdings nicht, dass das der ganze Text ist der durchsucht wird, da wird ja sicher noch mehr dabei sein, wie z.B. <html> und andere <div>s und all so Zeugs. In den drei Zeilen von dir ist der einzige endeutige Bereich das "class="info". Ich kann mir vorstellen, dass es im kompletten Quellcode mehrere <tables> oder mehrere <tr> und <td> gibt und auch mehrere <b>. An denen kann man sich schonmal nicht orientieren.

    Als Beispiel:
    Ausgangstext:

    HTML-Quellcode

    1. <table>
    2. <tr class='test'><td class='info' colspan="2"><b>benötigte Info</b></td></tr>
    3. <tr class='info'><td class='info2' colspan="1"><b>benötigte Info</b></td></tr>
    4. <tr class='test2'><td class='info' colspan="2"><b>benötigte Info</b></td></tr>
    5. <tr class='info'><td class='test2' colspan="4"><b>benötigte Info</b></td></tr>
    6. <tr class='info2'><td class='info' colspan="2"><b>benötigte Info</b></td></tr> <!-- Ich will nur den benötigten Text in der Zeile -->
    7. <tr class='info'><td class='info2' colspan="2"><b>benötigte Info</b></td></tr>
    8. <tr class='test'><td class='info' colspan="1"><b>benötigte Info</b></td></tr>
    9. <tr class='info'><td class='test2' colspan="1"><b>benötigte Info</b></td></tr>
    10. <tr class='test'><td class='info' colspan="1"><b>benötigte Info</b></td></tr>
    11. </table>


    Und jetzt schau dir die einzelnen Pattern an, je allgemeiner desto mehr Möglichkeiten (und Ergebnisse), je mehr eindeutige Textstellen, desto besser kann ich meinen Pattern ausformulieren.
    - <b>.*?<\/b> - Zu Allgemein, 9 Möglichkeiten und ich will nur eine Information
    - class\=\'info2\'.*?<b>.*?<\/b> - Schon besser, nur noch 3 Möglichkeiten
    - <tr +class\=\'info2\'.*?class\=\'info\'.*?<b>.*?<\/b> - Gut, nur eine Übereinstimmung.

    Du siehst, im dritten Pattern ist die Wahrscheinlichkeit dass ich tatsächlich das finde was ich will wesentlich höher, weil es vor und nach dem Text den ich finden möchte mehr Zeichen gibt, die ich zur Abfrage mit einbeziehen kann. Mit RegEx geht's ja darum, den Pattern so auszuarbeiten dass die Ergebnisse so genau wie möglich sind.


    würde ich ab und zu auch die pragmatische Variante nehmen

    Niemals! xD Es muss immer RegEx sein bei mir :D


    Link :thumbup:
    Hello World

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Link275“ ()

    Link275 schrieb:

    Ich glaube allerdings nicht, dass das der ganze Text ist der durchsucht wird, da wird ja sicher noch mehr dabei sein, wie z.B. <html> und andere <div>s und all so Zeugs.


    Es ist tatsächlich so, dass alles, was eigentlich um diese 3 Zeilen herum war, schon weggeschnitten wurde. Von daher ist es also eigentlich immer dasselbe, was gesucht wird. Das Gesuchte befindet sich auch immer an derselben Stelle. Das Problem, was ich mit RegEx halt umschiffen wollte, ist bloß, dass diese Informationen halt immer unterschiedlich lang sind. Vielleicht habe ich mich im Startpost auch etwas unglücklich ausgedrückt, aber ich suche wirklich jede Information in dem String, den ich untersuche, also in deinem Beispiel oben alle "benötigte Info", die sich im gesamten Abschnitt finden lassen.

    @diylab: Wenn ich mir das jetzt so anschaue, dann frage ich mich schon, warum ich nicht selbst drauf gekommen bin. Vielleicht weil ich immer zu kompliziert denke, streng nach dem Motto: "Warum einfach, wenns auch kompliziert geht" :) Aber danke für den Vorschlag, den werde ich unter Umständen später im Projekt in veränderter Form brauchen (wenn ich nicht wieder zu kompliziert denke :D).

    MfG bomberman2910