RegEx Tutorial - Blutige Anfänger und Fortgeschrittene

    • VB.NET

    Es gibt 56 Antworten in diesem Thema. Der letzte Beitrag () ist von razzzer530i.

      RegEx Tutorial - Blutige Anfänger und Fortgeschrittene

      Hi comm und Leute von außerhalb des Forums,

      -> Dieses Tutorial richtet sich an blutige Anfänger und alle die bereits schon Erfahrungen mit RegEx haben<-
      RegEx braucht man einfach so gut wie immer wenn man professionell mit Strings arbeiten möchte.



      Was durchgenommen wird

      • Einführung (was ist RegEx, wofür ist es gut)
      • Erklärung der verschiedenen Zeichen
      • Escapen (was bewirkt es, was bedeutet escapen)
      • Code Snippets (Code-Schnippsel)
      • Ersetzungen ( ?<X>expr <-> ${X})
      • Beispielprojekt zum ausprobieren in Visual Basic


      Bevor wir anfangen können, müssen einige wenige Vorbereitungen getroffen werden:

      - Visual Basic muss installiert sein, davon ausgehend, dass Sie Ihr neu erworbenes Wissen direkt in die Tat umsetzen möchten ;)
      - Zeit und Lust :)
      - Lernbereitschaft, selbsterklärend
      - und das wichtigste, die Klasse System.Text.RegularExpressions muss importiert werden (wie bei allen imports-Anweisungen ganz oben im Code).

      So wird's gemacht:

      VB.NET-Quellcode

      1. Imports System.Text.RegularExpressions


      Kurz ein Wort zur Ersetzung.
      Moment mal, wieso brauchen wir dafür RegEx? VB stellt uns doch bereits ein eine Ersetzen-Funktion (Replace) zur Verfügung. Allgemein bekannt sieht das dann in etwa so aus:

      VB.NET-Quellcode

      1. Dim var As String = "Das Wetter ist heute schön"
      2. var = var.Replace("heute", "heute nicht")


      Da wir das bereits kennen, ist nun die Frage, wozu wir zum Ersetzen noch RegEx brauchen. Das ist schnell erklärt, und jeder kennt die Situation: Manchmal möchte man nur bestimmte Muster eines Textes ersetzen, z.B. nur Wörter die mit "a" beginnen, oder nur Zahlen ersetzen, oder einfach nur alles ersetzen was zwischen zwei "" steht. Und das ist etwas, was mit der normalen Replace Funktion nur sehr schwer, und bis zu einem gewissen Grad teilweise gar nicht mehr zu bewerkstelligen ist. Zu Replace gleich noch Beispiele, zuerst wollen wir uns jedoch die alles entscheidende Kernfrage stellen, die da lautet ...

      Was ist denn nun RegEx?
      RegEx steht für "Regular Expressions", zu Deutsch "Reguläre Ausdrücke", oft auch "RegExp". Hierbei können bestimmte Zeichen verwendet, um die Suche nach bestimmten Textstellen oder -mustern zu matchen und nichtgewolltes leichter auszuschließen. Zur Veranschaulichung: Mit folgendem Code ist es uns möglich, alle Wörter die mit "a" anfangen und mit "en" enden zu entfernen, dafür ersetzen wir einfach mit "", also mit nichts, das Gefundene wird somit entfernt:

      VB.NET-Quellcode

      1. RichTextBox1.Text = RegEx.Replace(RichTextBox1.Text, "(^|\s|\n)a[a-z]+en(\n|\s|$)", "", RegexOptions.IgnoreCase)

      Es ist noch nicht wichtig den Ausdruck zu verstehen, das kommt alles dran, also keine Panik wenn Ihr mit diesem kryptischen Stück Code noch nichts anfangen könnt. Nach diesem Tutorial wisst Ihr all das richtig einzuordnen. Zunächst einmal ist zu sehen, das RegEx.Replace() hier mit 4 Parametern aufgerufen wurde:
      - dem EingabeString, das ist der Text aus dem etwas ersetzt werden soll, hier der Text in der RTB
      - der Reguläre Ausdruck, der den EingabeString -die RTB in unserem Fall- nach einem bestimmten Muster durchsucht
      - der Ersetzen-Zeichenkette, diesmal "", also eben nichts, und
      - der Suchoption, in unserem Beispiel wurde Groß-/Kleinschreibung ignoriert. Dieser, also der 4. parameter ist optional.

      Aber was ging da vor sich? Einige Zeichen im Suchmuster werden als Reguläre Ausdrücke behandelt und können so nicht im Text als Strings gefunden werden. Der Punkt . hat als Ausdruck eine eigene Bedeutung, er steht hierbei für ein beliebiges Zeichen. Das können Sonderzeichen sein, Buchstaben oder Zahlen, Tabstopps, Zeilenumbrüche, Textanfänge oder -enden. Der Ausdruck a.s würde also Beispielsweise die worte "als", "aus" oder "ass" finden, da das wort mit "a" beginnt, dem ein beliebiges Zeichen folgt und danach ein "s". Auch "a8s" oder "a!s" würde gefunden werden. Dem Fortgeschrittenen wird aufgefallen sein, dass das hier natürlich kein Wortanfang sein muss, auch "Haus" würde gefunden werden, dazu kommen wir aber gleich ;) -> Würde man nach Sonderzeichen als Strings suchen wollen geht das auch, wie, erfahrt ihr weiter unten, anzumerken hier auch Stichwort "escapen"


      Hier eine Liste der Ausdrücke, deren Funktion und einem Beispiel:

      . Beliebiges Zeichen
      Beschreibung: Der . entspricht einem beliebigen darstellbaren Zeichen (abhängig von den RegExOptions werden whitespace-Zeichen gefunden oder auch nicht)
      Beispiel: h.se findet "hase", "hose" oder auch "h9se"
      h.s. findet "hass", "hast" oder "Schiss". Aber wieso "Schiss"? Ganz einfach, weil vor "h" oder nach dem letzten "s" kein Leerzeichen
      steht, dieser Suchausdruck kann auch innerhalb eines Wortes sein.


      * 0 oder mehr Vorkommen
      Beschreibung: Findet 0 (null) oder mehr Vorkommen des vorangehenden Ausdrucks und ergibt somit alle möglichen Übereinstimmungen.
      Beispiel: "Han*es" findet "Hannes", "Hannnnnes" oder "Hannnnnnnnnnes" aber auch "Hanes" und sogar "Haes"(wie gesagt, möglich ist 0 oder mehrmals). "Ha.*es" findet "Hannes", "Hastiges" oder "Haltendes" aber auch "Ha325!%es", da ja nicht festgelegt ist, welche Zeichen innerhalt des Wortes erlaubt sind, aber das kommt nachher noch alles mit "[" und "]". Um ".*" mal in Worte zu fassen: Der Ausdruck sucht "Ha", wenn gefunden, wird alles was dann kommt ebenfalls positiv gematcht. In dem Fall ".*" was soviel heißt wie "ein beliebiges Zeichen beliebig oft oder gar nicht". Und am Ende dann irgendwann "es". Für den größeren Teil der Leser dieses Tuts wird es jetzt verwunderlich sein wenn Ich sage, dass damit auch "Ha123xyz!eseseseseseses" gefunden würde, wir haben nicht festgelegt, dass die Übereinstimmungssuche gleich beim ersten vorkommen von "es" enden soll. Auch dafür gibt es eine Lösung, lest weiter, Ihr werdet wissen wann die Stelle kommt ;)


      + 1 oder mehr Vorkommen
      Beschreibung: Findet mindestens ein oder beliebig viele Vorkommen des vorangehenden Ausdrucks
      Beispiel: Im Gegensatz zu * würde bei Han+es zwar auch "Hanes" "Hannes" oder "Hannnnnnnes" und so gefunden werden, jedoch NICHT "Haes", da der Ausdruck mindestens einmal vorkommen muss


      ^ Anfang des String / der Zeile
      Beschreibung: Bezeichnet den Anfang eines Strings oder einer Zeile (je nach dem bei RegExOptions festgelegten Wert(en))
      Beispiel: ^d Findet ein "d" nur, wenn es am Anfang des Strings steht, der Ausdruck ^.* findet Beispielsweise die erste Zeile des Strings bis zum Zeilenumbruch oder zum Textende, falls es nur eine Zeile ist.


      $ Ende des String / der Zeile
      Beschreibung: Bezeichnet das Ende eines Strings oder einer Zeile (je nach dem bei RegExOptions festgelegten Wert(en))
      Beispiel: Wie ^ nur dass es mit $ das Ende eines Strings ist. Wäre der zu durchsuchende String nun:
      "Ich schreibe gerade einen Teststring" und würden wir nach ...$ suchen, so würden wir "ing" finden.


      ? 0 oder 1 Vorkommen
      Beschreibung: Der vorangehende Ausdruck kommt 0x (also gar nicht) oder 1x vor.
      Beispiel: a.* (<- am ende ein leerzeichen!!!) findet im String "a b c d" nur "a b c ", da logischerweise nach "d" kein leerzeichen kommt. Mittels .* wird bis dahin gesucht, was nach dem "*" steht, steht da nichts, dann wird höchstens bis zum nächsten Zeilenumbruch gesucht. ABER mit dem ? Zeichen wird nur bis zum >ERSTEN< Vorkommen des nächsten Zeichens gesucht, also was nach dem ? kommt. Schreiben wir nun ein Fragezeichen dazu, also a.*? , so wird nur "a " gefunden, da nach diesem ja bereits schon das nächststehende Leerzeichen kommt. Komischerweise scheint das mit dem "?" in der VB-Hilfe vergessen worden zu sein. Also a.*? findet alle wörter die mit "a" anfangen, und bis dahin, wenn ein Leerzeichen kommt. Im Text "Das ist mein RegEx-Tutorial fürs VB-Paradise Forum" würde mit dem eben genannten Suchausdruck "as ", "al " und "adise" gefunden werden. Würden wir bei dem Suchmuster vor dem "a" auch noch ein Leerzeichen platzieren, so würden wir im eben beschriebenen Text nichts finden da dort kein wort mit "a" anfängt.


      \n Zeilenumbruch
      Beschreibung: Findet Zeilenumbrüche
      Beispiel: Hier mal ein Test-text:
      "Heute bin ich so mo
      tiviert, dass ich angefangen h
      abe, ein Tutorial für das Foru
      m zu schreiben."
      So, und wenn wir nun nach .\n. suchen würden, dann würden wir folgende Strings finden: "ot", "ha" und "um". Suchen wir nach ^.*?\n so erhalten wir die komplette erste Zeile.


      ===== Weiter im nächsten Post =========================================================================================================================


      Hello World

      Dieser Beitrag wurde bereits 17 mal editiert, zuletzt von „Link“ ()

      Hier der Zweite Teil

      \s Whitespace-Zeichen
      Beschreibung: Findet alle Whitespace-Zeichen (= nicht-anzeigbare Zeichen wie etwa Zeilenumbruch, Tab, Leerzeichen etc..)
      Beispiel: \s findet alle Zeichen die nicht dargestellt werden.

      \t Whitespace-Zeichen
      Beschreibung: Findet alle Tabulatoren-Zeichen
      Beispiel: \t findet alle Zeichen die nicht dargestellt werden.

      [...] Beliebiges Zeichen in der Menge
      Beschreibung: Findet eines der Zeichen, die in den eckigen Klammern enthalten sind. Geben Sie zum Festlegen eines Bereichs von Zeichen das Start- und das Endzeichen durch einen Bindestrich (-) getrennt ein, wie in [a-z]. Beispiel: "\sF[aeiou]s.*?\s" Findet Worte die mit "F" anfangen und danach einen Selbstlaut(also einen der Buchstaben in den eckigen klammern) haben bis zum nächsten Leerzeichen, also Beispielsweise " Fasan ", " Fussball " oder " Fasten ", gefoch nicht "Frisch", "Flug" oder "Franz", da hierbei nach dem "F" keiner der Buchstaben a,e,i,o oder u kommt(also keiner DIREKT nach dem "F") "[a-z0-9]" findet jedes (einzelne) Zeichen wenn es ein Buchstabe oder eine Zahl ist. Mit dem "+" kann hierbei praktischerweise die Übereinstimmung fortgesetzt werden. Im Text "In diesem Text kommen auch Zahlen vor, wie 1, 23, 300 oder 19" finden wir mit dem Suchmuster "\s[a-z ]+" Beispielsweise vom Wort "dem" bis zu der Stelle an der die Zahlen anfangen, da zahlen im Alphabet nicht vorkommen(PS: ab dem Wort "dem" deshalb, weil wir davor ein "\s" haben!! Und noch eine Falle: wir haben nach dem "z" in "[a-z ]" ein leerzeichen, hätten wir das nicht, würden wir NUR das wort "dem" finden, da Leerzeichen auch nicht im Alphabet enthalten sind! Immer gut aufpassen!). Im Text "8723 das waren zahlen, hier kommen noch mehr: 876578345" finden wir mit dem suchmuster "^[0-9]+" nur den ersten Zahlenblock, da ab dem Leerzeichen abgebrochen wird, welches ja ebenfalls bei den Zahlen 0-9 nicht enthalten ist.


      [^...] Beliebiges Zeichen nicht in der Menge
      Beschreibung: Findet ein beliebiges Zeichen, das nicht im Satz von Zeichen nach ^ enthalten ist. Die Bedeutung des ^-Zeichens ist hier nicht mehr das Anfang des Strings/der Zeile.
      Beispiel: Ha[^nu]s findet "Hals" aber nicht "Hans" oder "Haus".


      (...)Gruppierung
      Beschreibung: Ermöglicht es Ihnen, einen Satz von Ausdrücken zu gruppieren. Wenn du nach zwei verschiedenen Ausdrücken suchen magst, kannst du diese mit dem Gruppierungsausdruck kombinieren.
      Beispiel: ([0-9][a-z])+ findet alle Zeichenfolgen, wenn abwechselnd eine Zahl und dann ein Buchstabe folgt. Im String "3h4g9w2g6b5y0lzdh3j2q8f62441" würde gefunden werden: "3h4g9w2g6b5y0l" und "3j2q8f". Oder leichter Dargestellt: Im String "0F0F0F0F0FFFFFF0F0F0F0000" würde gefunden werden: "0F0F0F0F0F" und "0F0F0F". Mithilfe der Gruppierung kann man mehrere Ausdrücke einfach miteinander verketten. Äußerst interessant sind gruppierte Ausdrücke wenn es später dann auch um's Ersetzen geht.


      | ODER
      Beschreibung: Findet entweder den Ausdruck vor oder nach dem Symbol |-Zeichen. Wird meistens in einer Gruppe verwendet.
      Beispiel: (ab|ein|aus|um|allein)gang findet die Strings "abgang", "eingang", "ausgang", "umgang" und "alleingang". Hierbei wird wird mit ODER gearbeitet, kommt also ein Ausdruck nicht vor, wird der nächste probiert. Der Ausdruck ver(sau|ursach|schwende|damm)t findet "versaut", "verursacht", "verschwendet" und "verdammt". Ist logischerweise nicht wie ver[a-z]+t zu behandeln, da die Strings die zwischen "ver" und "t" stehen vorgegeben sind, und nicht beliebig auftauchen.


      \ Escape-Zeichen
      Beschreibung: Findet das Zeichen, das dem umgekehrten Schrägstrich \ als Literal folgt. Damit kannst du Zeichen wie { und ^ suchen, die in der Notation normalerweise für reguläre Ausdrücke verwendet werden.
      Beispiel: Mit \. kann in einem Text nach dem Punkt als String gesucht werden. ..\$ findet beispielsweise nicht das Zeilenende, sondern den Text "ab$" oder "var$". Der Ausdruck <.*?> findet alles was zwischen zwei "<>" steht, also beisp "<title>" oder "</body>". Der Ausdruck \[.*?\] findet alles was zwischen zwei [ ] (eckigen Klammern) steht, also "[Wort]", "[autorun]" und so weiter. Das \ vor "[" und "]" ist wichtig, damit die [] Zeichen als String erkannt werden können. Das ist nötig bei jedem Zeichen, welches in der RegEx-Notation eine spezielle Bedeutung hat. Also statt "+" nach \+ suchen, statt "/" ein "\/" oder statt "." ein "\.", naja ihr versteht schon.


      {...} fest definierte Anzahl an Vorkommen
      Beschreibung: Gibt an, wie of der vorangehende Ausdruck minimal, maximal oder minimal und maximal vorkommen darf.
      Mögliche Zustände:
      [0-9]{4, 8} Mindestens 4 und höchstens 8 Zahlen nacheinander
      [0-9]{4,} Mindestens 4 Zahlen oder beliebig viele
      [0-9]{,8} Beliebig viele Zahlen, aber mindestens 8
      [0-9]{5} Genau 5 Zahlen
      Beispiel: [0-9]{4} findet alle Strings die nur aus Zahlen bestehen und vierstellig sind. Findet beispielsweise "8932", "5897" und "2385" in "8932589723857".



      ==============================================================================================================================

      Weitere Infos / am Rande:
      Spoiler anzeigen

      Bei \d \w \s handelt es sich um sog. "vordefinierte Zeichenklassen". Vordefiniert deswegen, weil z.B. \d nichts anderes ist als [0-9] nur abgekürzt. Genauso wie \w auch gleichbedeutend ist mit [a-z_A-Z0-9]
      Hinweis: Großgeschriebene vordefinierte Zeichenklassen bedeuten jeweils das Gegenteil. So findet man mit \D alles außer Ziffern, mit \W alles außer Ziffern, Buchstaben und Unterstrich und mit \S alle Nicht-Whitespace-Zeichen (im Endeffekt alle Zeichen die sich darstellen lassen).




      Außerdem (falls es dich interessiert):
      Immer wenn man festlegt, wie oft ein vorangehender Ausdruck vorkommt (wie z.B. bei * oder + oder ? oder {3,7} dann handelt es sich um sog. "Quantoren".




      Es gibt noch die Ausdrücke
      - \n (UNIX-Zeilenumbruch)
      - \r (MAC-Zeilenumbruch) und
      - \r\n (Windows Zeilenumbruch)




      \b bezeichnet eine Wortgrenze.




      Gruppen können nicht nur via Gruppennummer (eine Gruppe hat automatisch eine Nummer, pro öffnende Klammer beginnt eine Gruppe) angesprochen werden, sondern ihnen kann auch ein Name zugewiesen werden.
      Beispiel: (?<gruppe1>[aeiou]) ist eine Gruppe in der alle gefundenen Selbstlaute drin sind. Bei der Ersetzung kann anstatt wie sonst über $1 bzw. ${1} nun auch über ${gruppe1} auf die Matches zugegriffen werden.




      In VisualBasic kannst du mehrere RegExOptions mittels AND auch verknüpfen und diese direkt so als Argument übergeben.


      ==============================================================================================================================



      So, jetzt können wir eigentlich auch schon loslegen. Wir starten nun einfach einmal ein
      Beispielprojekt
      Dafür holen wir uns
      1x TextBox
      1x RichTextBox
      1x ListBox
      1x CheckBox

      Wenn wir das alles schön positioniert haben, gehen wir in den Code-Editor und erstellen dort eine Sub. Nennen wir mal sie FilterExpr()

      VB.NET-Quellcode

      1. Imports System.Text.RegularExpressions
      2. Public Class Form1
      3. Sub FilterExpr(ByVal FilterObject As String)
      4. End Sub
      5. End Class

      Nun füllen wir die Sub wie folgt:

      VB.NET-Quellcode

      1. Imports System.Text.RegularExpressions
      2. Public Class Form1
      3. Sub FilterExpr(ByVal FilterObject As String)
      4. Dim Results As New List(Of String) 'Res als List
      5. Dim Curr As String = ""
      6. ListBox1.Items.Clear() 'ListBox items leeren
      7. Dim MC As MatchCollection 'Deklariere MC als MatchCollection
      8. 'Je nachdem ob CheckBox1 gecheckt ist, wird Groß- und Kleinschreibung ignoriert oder auch nicht:
      9. If CheckBox1.Checked Then
      10. MC = Regex.Matches(RichTextBox1.Text, FilterObject, RegexOptions.IgnoreCase) 'Wenn gecheckt, wird sie ignoriert
      11. Else
      12. MC = Regex.Matches(RichTextBox1.Text, FilterObject, RegexOptions.None) 'andernfalls wird darauf geachtet
      13. End If
      14. For i As Integer = 0 To MC.Count - 1 'Schleife durchlaufen
      15. If Results.Contains(MC(i).Value) = False Then
      16. Curr = MC(i).Value.ToString
      17. ListBox1.Items.Add(Curr) 'Übereinstimmungen in der ListBox eintragen
      18. End If
      19. Next
      20. End Sub
      21. 'Dann in TextBox1_TextChanged:
      22. Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
      23. If Not TextBox1.Text = "." And Not TextBox1.Text = " " And Not TextBox1.Text = "" Then
      24. FilterExpr(TextBox1.Text) 'Unsere Sub FilterExpr wird aufgerufen
      25. End If
      26. End Sub
      27. 'Und noch in RichTextBox1_TextChanged:
      28. Private Sub RichTextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles
      29. RichTextBox1.TextChanged
      30. FilterExpr(TextBox1.Text)
      31. End Sub
      32. End Class


      Mit diesem Projekt wird es ab jetzt richtig spannend, wenn wir unser neu erworbenes Wissen gleich in die Tat umzusetzen. Wir debuggen erstmal und schauen, ob alles glatt geht.
      Doch bevor es ans Werk geht: Kopiert euch wenn Ihr wollt einfach schnell diesen von mir gewählten Beispieltext in die RTB(zwischen den ===========). Er enthält viele verschiedene Textmuster und ist praktisch, um auch kompliziertere Code zu matchen

      ===========================================================================
      Spoiler anzeigen

      Sub FilterExt(ByVal FilterObject As String)
      Dim Results As New List(Of String)
      Dim Curr As String = ""
      ListBox1.Items.Clear()
      Dim MC As MatchCollection
      If CheckBox1.Checked Then
      MC = Regex.Matches(RichTextBox1.Text, FilterObject, RegexOptions.IgnoreCase)
      Else
      MC = Regex.Matches(RichTextBox1.Text, FilterObject, RegexOptions.None)
      End If
      For i As Integer = 0 To MC.Count - 1
      If Results.Contains(MC(i).Value) = False Then
      Curr = MC(i).Value.ToString
      ListBox1.Items.Add(Curr)
      End If
      Next
      End Sub


      <!DOCTYPE html>
      <HTML dir=ltr xml:lang="de" xmlns="http://www.w3.org/1999/xhtml"><HEAD><TITLE>[VB 2008] Irgendein Thread - Allgemein - Visual-

      Basic-Forum VB-Paradise</TITLE>
      <META content="text/html; charset=UTF-8" http-equiv=content-type>
      <META content=text/javascript http-equiv=content-script-type>
      <META content=text/css http-equiv=content-style-type>
      <META name=description
      content="Visual-Basic-Forum VB-Paradise: Alle Themen rund um die Programmiersprache Visual Basic (VB 6.0 / .NET, VBA, VBS, ASP).

      Inkl. Tipps-Bereich, Sourcecode-Austausch und Showroom für eigene Programme.">

      Hier noch eine Test-email (wieso? das erfahrt ihr weiter unten ;))
      Max-Muster@gmx.net
      Brenn.Punkt@FreeMail.net

      Eine Uhrzeit: 23:15:18,42

      +++ Ende des Testtextes +++ Ende des Testtextes +++ Ende des Testtextes +++ Ende des Testtextes +++ Ende des Testtextes +++

      ================================================================================================================================
      Hello World

      Dieser Beitrag wurde bereits 10 mal editiert, zuletzt von „Link“ ()

      Fortsetzung zweiter Teil

      Diesen Text lass ich euch mal zum kopieren da, ist ganz praktisch zum üben eben. Selbstverständlich könne Ihr auch eure eigenen Texte nehmen ;).

      Jetzt könnt ihr nach Lust und Laune herumexperimentieren. Versucht zum Beispiel mal den Ausdruck <.*?> und schreibt Ihn in die TextBox.
      Oder auch \Dim .*?\s As .*?(\s|\n)
      Ist ganz interessant, das ganze mal auszuprobieren, damit kann man sich erst einmal ein wenig einarbeiten in die ganzen RegEx-Codes.
      Es muss nicht immer eine eigene Sub sein, beispielsweise wenn man nur kurz etwas ersetzen will. Dafür reicht folgende kleine Codezeile:

      VB.NET-Quellcode

      1. RichTextBox1.Text = RegEx.Replace(RichTextBox1.Text, "\s...\s", "", RegExOptions.IgnoreCase)

      damit entfernt man z.B. alle Worte mit 3 Zeichen.

      Was kann RegEx noch alles?

      Nun, da Ich es am leichtesten finde, immer gleich alles zu testen, schlage Ich vor, wir erstellen uns ein neues Projekt oder
      lassen das schon erstellte offen und fügen dort einen Button hinzu. Jetzt wollen wir überprüfen, ob denn überhaupt in der RichTextBox ein
      vordefiniertes Suchmuster vorhanden ist. Das machen wir mit RegEx.IsMatch(), ist eigentlich das ähnliche wie RichTextBox1.Text.Contains(), nur dass wir auch hierbei wieder Reguläre Ausdrücke angeben können, nach dessen Muster gesucht werden soll. Dafür erstellen wir zuerst eine Variable vom Typ Boolean, die am Ende angibt, ob ein solches Muster gefunden wurde.

      VB.NET-Quellcode

      1. Dim Exists As Boolean = Regex.IsMatch(RichTextBox1.Text, "\sa[a-z]+en\s", RegExOptions.IgnoreCase)
      2. If Exists Then MsgBox("Es sind Übereinstimmungen Ihres Suchmusters vorhanden.")

      In diesem Beispiel matcht RegEx ein Wort, welches mit "a" anfängt und mit "en" aufhört, also beispielsweise "arbeiten", "ahnen" oder "aufpassen". Wie immer pfeifen wir auf Groß- Kleinschreibung ;) Somit werden zwar die gesuchten Strings nicht ausgegeben, aber es wird geprüft, ob ein solches Muster überhaupt auftaucht.

      Wir können mit RegEx natürlich auch Strings splitten. Dafür brauchen wir lediglich einen InputString, d.h. der String in dem gesucht werden soll.
      Ich habe zum testen einfach mal folgenden genommen:

      VB.NET-Quellcode

      1. Dim Input As String = "Ich gehe heute mit meinem Hund spazieren"

      Wir legen dann eine weitere Variable an vom Typ String-Array, dort "lagern" wir dann die gesplitteten Strings:

      VB.NET-Quellcode

      1. Dim Input As String = "Ich gehe heute mit meinem Hund spazieren"
      2. Dim Res() As String
      3. ListBox1.Items.Clear()
      4. Res = Regex.Split(Input, "\s[a-z]+\s", RegexOptions.IgnoreCase)
      5. For Each el As String In Res
      6. ListBox1.Items.Add(el.ToString)
      7. Next

      Würden wir nun den String von "Input" in die RichTextBox1 schreiben und dann in unserer TextBox diesen Suchausdruck:
      (\s[a-z]+\s)
      eingeben, so fänden wir "gehe", "mit" und "Hund". Wenn wir aber auf unseren Button klicken wird gesplittet und übrig bleibt "Ich", "heute", "meinem" und "spazieren".

      **************************************************************************************************
      So, jetzt haben wir eine Sub FilterExpr. Um mit RegEx noch besser üben zu können, können wir eine weitere Sub einbauen, nennen wir sie mal ReplaceStr(). Dieser übergeben wir 2 Parameter.

      VB.NET-Quellcode

      1. Sub ReplaceStr(ByVal Pattern As String, Optional ByVal Replacement As String = "")
      2. RichTextBox1.Text = RegEx.Replace(RichTextBox1.Text, Pattern, Replacement, RexEgOptions.IgnoreCase)
      3. End Sub

      Und so brauchen wir fortan zum ersetzen oder entfernen von Suchmustern nur noch die Sub aufrufen[ReplaceStr("Ausdruck", "Irgendwas oder nichts")]und sparen uns jedesmal die Tipperei.


      Sooo ... das war's auch schon mit diesem Tutorial. Ich hoffe es hat euch gefallen und Ihr habt was dazugelernt. Wenn das der Fall ist, hat es sich für mich gelohnt dieses Tutorial zu schreiben. Vergesst nicht, auf den "Bedanken"-Button zu klicken ;) Bei Fragen, Anregungen oder Wünschen, wenn noch was fehlt oder was dazu soll, dann kontaktiert mich einfach entweder über PN oder (besser) ihr schreibt es unten als Post dazu.



      Weitere Beispiele
      Es folgen jetzt noch ein paar Beispiele, falls bisher etwas unklar war einfach mal anschauen

      [Beispiel 1]
      Mit dem Ausdruck (.)\1 findet man alle Zeichen, die doppelt kommen (sich mind. 1x wiederholen). Zum Beispiel "Mann" oder "Starr" oder "Hummel". Das \1 bezeichnet eine Gruppe innerhalb des Patterns. Wenn man verschachtelte Klammern (=Gruppen) hat, so zählt man die Gruppen am besten immer über die erste geöffnete Klammer. Mit \1, \2, \3 etc.. kann man dann innerhalb des Patterns auf die Gruppen zugreifen. Ein Beispiel hierzu: ich möchte alle Wörter finden, die mit demselben Buchstaben enden mit dem sie auch beginnen (z.B. "anna" oder "stress" oder "cognac" oder "uhu". Der Pattern dafür ist \b([a-z])[a-z]+\1\b. Mal kurz aufgeschlüsselt das Ganze: \b bezeichnet wie wir wissen eine Wortgrenze. Danach folgt ein Buchstabe (in Klammern, also eine Gruppierung). Mit [a-z]+ suchen wir weitere Buchstabenfolgen (es muss mind. 1 Buchstabe kommen). Anschließend soll nochmal der gleiche Ausdruck wie in Gruppe 1 vorkommen (was ja ein Buchstabe ist) und das \b stellt erneut unsere Wortgrenze dar.

      [Beispiel 2]
      Wir haben einen String: "Wenn mir langweilig ist, gehe ich raus oder lese 1-2 Stunden." (ohne die ") Wir gehen in den folgenden Beispielen davon aus, dass wir die Beispieltexte in unsere RTB kopieren und in der TextBox die Ausdrücke eingeben. So, worin unterscheidet sich Ausdruck1 von Ausdruck2(ohne das erste leerzeichen nach dem doppelpunkt):
      Ausdruck1: We.*\s
      Ausdruck2: We.*?\s
      Einfach mal beides versuchen, ist ganz interessant anzuschauen. Beim ersten Ausdruck finden wir den String "Wenn mir langwelig ist, gehe ich raus oder lese 1-2 " in der ListBox, beim zweiten Ausdruck finden wir "Wenn" und "weilig". warum? Weil wir beim ersten Suchausdruck von "We" angefangen suchen bis zum letzen leerzeichen vor dem Ende des Strings oder vor einem Zeilenumbruch. Da nach dem Letzen Wort(Stunden.) ja kein Leerzeichen mehr kommt, wird das nicht gefunden. Beim 2. Ausdruck haben wir noch ein "?" dazugeschrieben, was heißt, dass nur von der Zeichenfolge "we" bis zum nächststehenden Leerzeichen gesucht werden soll, das haben wir also einmal im wort "Wenn" und einmal in "langweilig". Anderes Beispiel: der String ist diemal folgender: "ente essen einzeln" Die Ausdrücke:
      Ausdruck1: e[a-z]+e[a-z]*
      Ausdruck2: e[a-z]+e[a-z]+
      Auch hier wieder der Spaß mit "+" oder "*"
      Ausdruck1 findet alle 3 Worte des Strings, Ausdruck2 findet nur "essen" und "einzeln". Warum? Weil bei "ente" der letzte Buchstabe das "e" ist und im Ausdruck aber steht, dass nach dem nächsten "e" noch mindestens ein Buchstabe kommen muss(-> "+" = 1 oder mehr vorkommen).




      So, das wär's nun gewesen, wenn mir noch etwas einfällt, werd ich nicht zögern, es dazuschreiben.
      Anbei hier noch einige nützliche RegEx-Codes:

      HTML-tags finden:
      <.*?>

      Wörter finden:
      \b[a-z]+\b

      Links aus HTML-Quelltext filtern:
      <a href\=(\"|\').*?\1>.*?<\/a>

      MAC-Adresse validieren:
      ([a-f0-9]{2}\-){5}[a-f0-9]{2}

      Windows-Dateipfade aufspüren:
      [a-z]\:\\.*\.[a-z]{1-4}

      Bilder finden:
      \S+\.(png|jpg|bmp|gif)

      Uhrzeit finden:
      (0.|[1][0-9]|[2][0-3])\:[0-5][0-9]\:[0-5][0-9]
      aber noch besser ist folgende Variante, da hierbei die Uhrzeit im format 23:15:39,44 vorliegen kann, aber auch 23:15:39 oder
      auch nur 23:15. Dasselbe funktioniert hierbei auch mit "-" oder "." als Trennzeichen statt nur mit ":"
      \s(0.|[1][0-9]|[2][0-3])(\:|\.|\-)[0-5][0-9]((\:|\.|\-)[0-5][0-9]|)(\,[0-5][0-9]|)\s

      ### CLSID anzeigen:
      \{[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\}

      IP-Adresse finden:
      (([0-9]|[1][0-9]|[1][0-9][0-9]|[2][0-5]{2})\.){3}([0-9]|[1][0-9]|[1][0-9][0-9]|[2][0-5]{2})

      Internetadressen finden:
      (https?\:\/\/(www\.)?)\S+\.[a-z]{2,4}

      Email adressen rausfischen:
      [a-zA-Z0-9|a-zA-Z0-9\.]+\@[a-zA-Z0-9|a-zA-Z0-9\-]+\.[com|de|net|mu]+
      oder:
      \w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
      oder:
      [a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|com|org|net|gov|biz|info|name|aero|biz|info|jobs|museum)\b

      Hex-Farbcodes finden:
      \#[a-f0-9]{6}
      oder auch (je nach Format):
      \#[a-f0-9]{3}


      ####### Visual Basic #######

      Variablen aufspüren:
      (dim|private|friend|static|public) [a-z0-9]+ As (new [a-z]+.*|[a-z]+)

      Importiertes
      (^|\n) *Imports .*?(\n|$)

      Kommentare finden
      \'.*

      Subs finden
      \s[a-z]+\ssub\s.*?\n
      Dasselbe einfach auch mit Function oder Property

      Variablen eines bestimmten Datentyps finden(hier String)
      \s(dim|private|friend|static|public) [a-z0-9]+ as (new [a-z]+.*string\)|string)

      True/False finden
      .*(True|False).*

      ### Event handler:
      \s[a-z]+\ssub [a-z0-9_\(\)\,\. ]+ handles [a-z0-9]+\.[a-z]+
      ### NUR die Handler:
      \shandles [a-z0-9]+\.[a-z]+
      ### Nur Subs/Functions ohne Parameter:
      ([a-z]+|) (sub|function) [a-z0-9_]+\(\)
      ### Nur Subs/Functions mit parametern:
      ([a-z]+|) (sub|function) [a-z0-9_\-]+\(((optional|byval|byref) .*?\)).*
      [/code]



      Ich bedanke mich nochmal für's Lesen meines Tutorials. Viel Spaß damit :thumbup:

      PS: Bitte an dieser Stelle abermals um Feedback oder Verbesserungsvorschläge :thumbup:


      Mittlerweile ist passend hierzu auch ein ziemlich guter RegEx-Tester im Forum erschienen.
      Mehr dazu:
      klick


      Link :thumbup:
      Hello World

      Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Link“ ()

      Feedback: Schaut gut aus, dein Tutorial, gut erklärt und mit Beispielen!

      Verbesserungsvorschlag: Bitte ein wenig besser strukturieren! Gib deiner Auflistung Verweise zu deinen Posts und gib jedem Thema auch eine große, gut erkennbare Überschrift. Die ganze Ansammlung an z.B. Notations könntest du noch in Expander packen - Das wäre um einiges übersichtlicher!

      Fazit: Dein Tutorial ist an sich sehr gut, leider nur unübersichtlich - Hab's mir aus dem Grund durchgelesen, dass ich mich morgen/heute damit auseinandersetzen muss... Finde es gut, aber es wird 'ne Arbeit, sich da durch zu wühlen :).

      MfG,
      X-Zat / Momo
      Erstmal Danke für dein Feedback :) Ich nehme deinen Vorschlag gerne an und überarbeite die Struktur, die nächste halbe Stunde wird's sicher fertig werden :)

      //EDIT: Ist es besser so? Oder was könnte noch geänder/verbessert werden?


      link_275 :thumbup:
      Hello World

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

      Sehr schönes Tutorial.
      Aber könntest du noch ergänzen, wie ich z.b. aus dem folgendem Satz:

      "Ich gehe heute mit meinem Hund, Namens Dieter spatzieren gehen. Sein Fell ist schwarz und kurz."

      -> den Namen des Hundes, seine Fellfarbe und felllänge rausfischen.
      In diesem Fall denke ich dass das so aussehen dürfte:

      Dim Name As String = ""
      Dim Fell As String = ""
      Dim FellLänge As String = ""

      RegEx.IrgendeineFunktion("der pattern oder so", "der beispielsatz oder so", Name, Fell, FellLänge)

      Damit will ich soz. aus dem Pattern - er sieht so aus:
      "Ich gehe heute mit meinem Hund, Namnes [HIER DER NAME] spatzieren gehen. Sein Fell ist [DIE FARBE HIER] und [LANG, GROß, KURZ, ...]."
      die Tags >[HIER DER NAME]< in die Variable Name eintragen, usw.

      Du verstehst wohlmöglich, was ich meine oder? :D
      Das Pattern müsste so aussehen

      Quellcode

      1. "Ich gehe heute mit meinem Hund, namens (?<dogname>(\s[a-zA-Z]+\s)?) spatzieren gehen. Sein Fell ist (?<doghaircolor>(\s[a-zA-Z]+\s)?) und (?<doghairlength>(\s[a-zA-Z]+\s)?)."
      wie du damit arbeitest steht ja im Tutorial
      Mhm..
      Mein Code sieht nun so aus:

      VB.NET-Quellcode

      1. Dim Sample As String = "Ich gehe heute mit meinem Hund, Namens Dieter spatzieren gehen. Sein Fell ist schwarz und kurz."
      2. Dim Pattern As String = "Ich gehe heute mit meinem Hund, namens (?<dogname>(\s[a-zA-Z]+\s)?) spatzieren gehen. Sein Fell ist (?<doghaircolor>(\s[a-zA-Z]+\s)?) und (?<doghairlength>(\s[a-zA-Z]+\s)?)."
      3. Dim Result As MatchCollection = Regex.Matches(Sample, Pattern)
      4. Dim Result_Name As String = Result(0).Value
      5. Dim Result_Color As String = Result(1).Value
      6. Dim Result_Length As String = Result(2).Value
      7. MsgBox(String.Concat("Name: ", Result_Name, " Color:", Result_Color, " Length:", Result_Length))


      Aber wenn ich es starte kommt das:

      Das angegebene Argument liegt außerhalb des gültigen Wertebereichs.
      Parametername: i

      bei Zeile: Dim Result_Name As String = Result(0).Value

      Habe ich die falsche funktion angewendet?
      #Edit: Ich bin jetzt schon da:

      VB.NET-Quellcode

      1. Dim Sample As String = "Ich gehe heute mit meinem Hund, Namens Dieter spatzieren gehen. Sein Fell ist schwarz und kurz."
      2. Dim Pattern As String = "Ich gehe heute mit meinem Hund, namens (?<dogname>(\s[a-zA-Z]+\s)?) spatzieren gehen. Sein Fell ist (?<doghaircolor>(\s[a-zA-Z]+\s)?) und (?<doghairlength>(\s[a-zA-Z]+\s)?)."
      3. Dim Result As Match = Regex.Match(Sample, Pattern)
      4. Dim Result_Name As String = Result.Groups(0).Value
      5. Dim Result_Color As String = Result.Groups(1).Value
      6. Dim Result_Length As String = Result.Groups(2).Value
      7. MsgBox(String.Concat("Name: ", Result_Name, " Color:", Result_Color, " Length:", Result_Length))


      aber Result.Length ist 0 und bei Groups(0), sowie bei 1 und 2 gibt es mir ein leeres Resultat zurück. :(

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

      Anlaufstellen die mir auffallen:
      du benutzt kein IgnoreCase und somit erkennt er "namens" nicht als "Namens" an
      ich habe den Gruppen extra Namen gegeben und diese nach Namen auszulesen
      Hi Leute, Ich hab' das Tut jetzt auch mal eben als *.PDF verfügbar gemacht, Ihr könnt es euch ansehen: vb-paradise.de/index.php/Attac…78e7f9b788e5bc028fafa1692
      oder hier als *.RAR herunterladen: RegEx_Tut.rar

      Wenn euch noch fehlerhaftes auffällt in der PDF, kontaktiert mich einfach :)


      hf link_275 :thumbup:
      Hello World

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

      Sehr schönes Tutorial, ich habe allerdings noch eine Frage!

      Bei mir tritt das Problem auf, dass es zwei gleich benannte Pattern gibt mit einem anderen Inhalt, möchte aber beide auslesen!

      Bsp.

      HTML-Quellcode

      1. <beispiel>Das ist ein Beispiel</beispiel>


      und

      HTML-Quellcode

      1. <beispiel>Das war ein Beispiel</beispiel>


      Wichtig ist vorallem, dass ich beide Werte in zwei verschiedene Labels haben möchte, allerdings ist dies schwer da sie beide die gleichen pattern haben.
      Dafür gibt es RegexMatches, welche tu in einer schleife durchlaufen kannst, z.B. so:

      VB.NET-Quellcode

      1. For Each m As Match in Regex.Matches(text)
      2. 'm ist das jeweilige Match
      3. Next
      Ich wollte auch mal ne total überflüssige Signatur:
      ---Leer---
      Mhhh, ich habe das Ganze jetzt auch noch nicht ganz verstanden.
      Man kann also, wie jvbsl schon gepostet hat, nach Übereinstimmungen suchen. Aber kann man auch nach
      einem "Ansatz" suchen? zB steht in einem Label "Hallo" und ich möchte nun nach dem Text suchen.
      Wenn ich also Hallo suche, finde ich den Text in dem Label, aber wenn ich nur nach Hall suche, sollte er es auch finden.
      Ist das möglich? Wenn ja, würde ich mich über ein Stichwort freuen :)

      Lg ~
      Na, da ich nicht der King der For Each whatever Schleifen bin, bräuchte ich mal eure Hilfe.

      Im Moment mache ich das so:

      VB.NET-Quellcode

      1. For Each m As Match In Regex.Matches(ListView1.Items(0).Text, TextBox2.Text, RegexOptions.IgnoreCase)
      2. MsgBox("Gefunden")
      3. Next


      Ich möchte aber alle Items durchsuchen. :/

      Wäre das dann so richtig?

      VB.NET-Quellcode

      1. For i = 0 To ListView1.Items.Count - 1
      2. For Each m As Match In Regex.Matches(ListView1.Items(i).Text, TextBox2.Text, RegexOptions.IgnoreCase)
      3. MsgBox("Gefunden")
      4. Next
      5. Next


      Lg ~
      Probier es doch aus, aber sollte richtig sein.

      Jetzt habe ich aber in fast jedem ListviewItem ein Treffer und ich werde mit Messageboxen zugespammt :D

      larserik98 schrieb:

      Wie geht das mit einem Datum?

      Z.b 20.05.2011
      Wie filtere ich das?

      Mit "[0-9]{2}\.[0-9]{2}\.[0-9]{4}"
      //Edit:
      Ich hätte noch eine Frage..
      Ich versuche aus einer URL (also z.B vb-paradise.de/index.php?form=PostEdit&postID=465909) nur das "http://www.vb-paradise.de", also nur den Domainnamen herauszufischen.. Mein Code sieht so aus:

      VB.NET-Quellcode

      1. Dim MyRegEx As New Regex("(http|https)\:\/\/+\/", RegexOptions.IgnoreCase)
      2. Dim Link As String = "http://www.vb-paradise.de/index.php?form=PostEdit&postID=465909"
      3. Console.WriteLine(MyRegEx.Match(Link))

      Aber es liefert immer nichts zurück..
      Dieser Pattern von link

      Quellcode

      1. (http\:\/\/|www.).*\.[a-z]{1-4}

      gibt aber auch nichts zurück.. jemand ne ahnung woran das liegt?
      --- Zurzeit inaktiv ---

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