RegEx Tutorial - Blutige Anfänger und Fortgeschrittene

    • VB.NET

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

      Hallo,

      bin hier zufällig über dieses Tutorial gestolpert. Ich nutze schon einige Jahre Reguläre Ausdrücke. Anfangs mit Perl zum analysieren von Log-Dateien.

      Jetzt bin ich etwas verwundert über die folgenden Punkte.

      1. Bis zum ersten Vorkommen '?'

      2. Markierter Ausdruck '{ ... }'

      3. Leerzeichen '\s'


      Jetzt bin ich etwas verwundert über die Erklärung - verwendet .NET keine Perl kompatiblen Regulären Ausdrücke? Nach meiner Erinnerung, sind doch beides einfache Quantoren. Liege ich da etwa seit einigen Jahren falsch?

      Meiner Meinung nach:
      Ist [0-9]{0,1} das gleiche wie [0-9]?
      Ist [0-9]{0,} das gleiche wie [0-9]*
      Ist [0-9]{1,} das gleiche wie [0-9]+

      Desweiteren zu Punkt 3. Ist der Wert doch kein Leerzeichen? Auch sämtliche Steuerzeichen wie \r, \t, (je nach modifier auch \n) ?
      Also erstmal das Tutorial ist gut. Ich konnte viel lernen und viel umsetzten. Doch dein Code um IP Adressen rauszu Filtern ist totaler schwachsinn. Habe ihn ausprobiert und er nimmt nicht alle 4 blöcke auf, sondern geht nur bis zum 3ten und beim 4 block nimmt er nur die erste Zahl. Noch dazu übernimmt er keine Ports. Habe es mal rausgearbeitet und das sieht bei mir jetzt so aus:

      VB.NET-Quellcode

      1. Regex.Matches(Input, "([0-9]{4}|[0-9]{3}|[0-9]{2}|[0-9])\.([0-9]{4}|[0-9]{3}|[0-9]{2}|[0-9])\.([0-9]{4}|[0-9]{3}|[0-9]{2}|[0-9])\.([0-9]{4}|[0-9]{3}|[0-9]{2}|[0-9]):([0-9]{5}|[0-9]{4}|[0-9]{3}|[0-9]{2}|[0-9])")


      wenn ihr noch bei mir ein fehler seht, dann entschulde ich mich dafür

      aber sonst, gutes Tutorial!
      Na ja, dein Pattern macht noch weniger Sinn, denn der findet nämlich auch IPs die so ausssehen: 2455.2455.2455.2685
      Des Weiteren findet er nur IPs mit nem Port.
      Kurz und knapp für IP oder IP:Port: (\d{1,3}\.){3}\d{1,3}(:\d{1,5})?
      Hi,

      @RushDen ja sicher kann man das. Aber RegEx is halt einfach geil. Bevor ich da umständlich mit substr, trim, split, strpos etc... rumfummel und am Ende so halbwegs ne Validierung hab die vielleicht irgendwie funktioniert mach ich nen RegEx-Einzeiler und gut is. Da mach ich persönlich keine Kompromisse ;)

      @Rinecamo: Kurz und knapp: nein. Weil 999 in einem IP-Oktett kein gültiger Wert is (in deinem Pattern jedoch zulässig wäre).

      @licere: Ja mag sein dass die Lösung echt nicht ideal ist, allerdings steckte mein Wissen über RegEx als ich das Tutorial gemacht hab auch noch mehr oder minder in den Kinderschuhen (wusste noch nicht dass es noch viel mehr gibt, Assertions (lookaround) werden ja z.B. gar nicht erwähnt etc..).

      @Real-TTX Gern geh ich darauf ein:
      1. Bis zum ersten Vorkommen '?'
      Je nachdem von welcher Seite aus man den Pattern betrachtet -hast du recht- könnte die Beschreibung aufn ersten Blick seltsam rüberkommen. Gemeint ist natürlich dass der vorangehende Ausdruck (oder eine Gruppe oder sonstwas) genau einmal folgt bis zum ersten Vorkommen des nächsten Ausdrucks (was nach "?" kommt).

      2. Markierter Ausdruck '{ ... }'
      Naja auch iwie schwammig^^ Oke klar abgesehn davon dass du's ja selber weißt was gemeint ist kann ich es noch kurz anders erklären. Also mit Angaben in geschweiften Klammern legt man die genaue Häufigkeit des vorangehenden Ausdrucks fest. Dabei kann man feste Werte(-bereiche) definieren, man kann aber auch nach oben sowie nach unten die Grenze offen lassen.
      Beispiel:
      {x,y} - vorangehender Ausdruck kommt wenigstens x mal aber höchstens y mal vor
      {x,} - vorangehender Ausdruck kommt beliebig oft vor, aber mindestens x mal
      {,y} - vorangehender Ausdruck kommt beliebig oft vor, aber höchstens y mal.
      {z} - vorangehender Ausdruck kommt genau z mal vor.

      3. Leerzeichen '\s'
      Jupp, is schmarrn (mehr oder weniger). Klar, "\s" matched unter anderem Leerzeichen. Weil das Leerzeichen ein Whitespace-Zeichen ist, und mit "\s" alle whitespace-zeichen gemeint sind.

      Zu den andren Sachen:
      Ist [0-9]{0,1} das gleiche wie [0-9]?
      Ja.

      Ist [0-9]{0,} das gleiche wie [0-9]*
      Ja, auch richtig.

      Ist [0-9]{1,} das gleiche wie [0-9]+
      Stimmt auch

      Funktioniert aber nur in genau der Konstellation (also mit den Werten 0 und 1). Um noch eine Konstellation zu probieren: Mann kann auch [0-9]{1} schreiben was dann das gleiche wäre wie einfach nur [0-9] ohne etwas dahinter.

      Desweiteren zu Punkt 3. Ist der Wert doch kein Leerzeichen? Auch sämtliche Steuerzeichen wie \r, \t, (je nach modifier auch \n)?
      Hab ich weiter oben bereits beantwortet. Aber ja du hast recht, meine Beschreibung war einfach schlecht^^.



      Link :thumbup:
      Hello World
      Hi hab jetzt net alles gelesen aber hier noch ein paar Ausdrücke:


      Name, Nachname ((Prof. )?(Dr. )?[A-Z][a-züÜöÖäÄHßé]+((\-|\ )[A-Z][a-züÜöÖäÄßéH]+)+)

      Straße + Hausnummer ([a-zA-ZäöüÄÖÜß \.]+) [0-9]{1,2}([0-9\-]?+)([ ][a-zA-ZÜüÖöÄäß]?+[0-9]?)?+

      Tel (((((((00|\+|0900)49[ \-\/\s\/s]?)|0)[1-9][0-9]{1,4})[ \-\/]?)|((((00|\+)49\()|\(0)[1-9][0-9]{1,4}\)[ \-\/]?))[0-9]{1,7}([ \-\/]?[0-9]{1,5})?(\-)?[0-9]{0,2})

      PLZ Ort ([0]{1}[1-9]{1}|[1-9]{1}[0-9]{1})[0-9]{3}([ ][\wüÜöÖäÄß]*){1,2}(\-)?([a-zA-ZÜüÖöÄäß]+)?|(([\wüÜöÖäÄß]*[ ]){1,2}([0]{1}[1-9]{1}|[1-9]{1}[0-9]{1})[0-9]{3})[ ](\-)?([a-zA-ZÜüÖöÄäß]+)?


      Email [a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*\s?(@|\(at\))\s?(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?

      Internetadresse ((www?)([a-zA-ZÜüÖöÄäß0-9\.\-\/]+)(\.[a-zA-ZÜüÖöÄäß]{0,2})([a-zA-ZÜüÖöÄäß\/]+)?)


      und noch gute Seiten zum testen:

      Links zu Online-Tools
      regex101.com
      http://www.regexe.de/

      Ich war mal so frei und habe die Patterns in InlineCode-Tags gesetzt. ~Thunderbolt

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

      Ist mit RegEx möglich, einen SubString zwischen zwei Codeworten zu bekommen?
      Also nicht zu löschen, oder zu replacen, meine das eher so:

      Codeword1
      Text der mich interessiert
      Codeword2

      Jetzt will ich aus dem oberen Textfeld bsp.
      "Text der mich interessiert" in ein zweites Textfeld bekommen?
      Codeword1 und 2 sind natürlich bekannt und immer gleich.
      Danke!

      Grüße,
      Kevin
      @Viercnt
      Klar geht das: Codeword1(?<Text>.*?)Codeword2 Dann kriegst du in der Group "Text" den gewünschten Text.

      Nachtrag:
      Alternativ wäre das auch mit einem LookAhead und einem LookBehind lösbar. Mehr dazu hier: Lookahead und Lookbehind - Zwei unbekannte aber hilfreiche RegEx-Funktionen

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

      Erst einmal: Vielen Dank für dieses tolle Tutorial!

      Aber trotz mehrtägigem Grübeln kriege ich nicht hin, was ich hinkriegen möchte. Folgendes Problem, bei dem ich für jeden Tip dankbar bin:

      In einer Kundendatenbank können die Benutzer neue Kunden eintragen. Natürlich sollen keine Duplikate eingetragen werden. Eine 1:1-Übereinstimmung zu finden ist kein Problem, auch teilweise Übereinstimmungen nicht, das habe ich bereits ohne RegEx realisiert. Aber hier scheitere ich und komme mit dem Code aus dem Beispielprogramm nicht weiter:

      Vorhandener Kunde in Datenbank: "Müller und Meier"

      Neuer Kunde: "Müller" - wird gefunden
      Neuer Kunde: "Meier" - wird gefunden
      Neuer Kunde: "Müller und Meier" - wird natürlich auch gefunden

      Aber:
      Neuer Kunde: "Müller und Meier GmbH" wird nicht gefunden.

      Ich habe also Teilstrings und vollständige Übereinstimmungen, aber wenn der String aus der Datenbank erweitert wird, hier um "GmbH" - das geht anstandslos durch.

      Wäre super, wenn mich irgendjemand auf die richtige Fährte setzen könnte.

      Danke an alle im Voraus.
      Hi,

      PHP-Quellcode

      1. <?php
      2. // Hier wird mal davon ausgegangen, dass es auf der vorherigen Seite ein Formular
      3. // gibt wo man nen Suchbegriff eingeben konnte.
      4. $pat = $_POST['suchbegriff'];
      5. $pat = ".*" . $pat . ".*";
      6. // Und jetzt die Daten abholen:
      7. $kunden = $pdo->query("SELECT name FROM `tbl_kunden` WHERE name REGEXP " . $pdo->quote($pat) . "")->fetchAll();
      8. echo "<pre>" . print_r($kunden, 1) . "</pre>";
      9. # Fertig
      10. // Achtung: du kannst auch Leerzeichen im Suchbegriff ersetzen durch Pipe-Zeichen (das hier: | ) allerdings würde dann jedes
      11. // Leerzeichen ein "ODER" bedeutet. Aber da musst du dich bisschen spielen und ausprobieren. Im Optimalfall
      12. // übergibst du den Suchbegriff so wie er eingegeben wurde (ohne dass du davor und dahinter was hinzufügst so wie oben) und
      13. // setzt halt voraus dass man ein bissl RegEx kann. Weil dann ist man halt wirklich flexibel damit. Und es lohnt sich wenn man
      14. // damit ein bissl klar kommt.
      15. // Tipp: wenn du eine vollständige Übereinstimmung mit RegEx erreichen willst (so ist es ja momentan bei dir ohne RegEx) schreibst du
      16. // quasi "^suchbegriff$". Aber dafür braucht man dann ja kein RegEx :P
      17. ?>



      Link :thumbup:
      Hello World

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

      Moin,

      ist zwar schon alt der Post, aber ich kriege eine Sache nicht hin.
      Ich habe folgendes Problem:

      Strings vorhanden:
      COMP900A
      COMP900B
      COMP150
      COMP250
      COMP330
      .........
      ok ist der ausdruck nur, wenn 4 buchstaben von 3 zahlen gefolgt werden aber die erste zahl keine 9 ist.

      VB.NET-Quellcode

      1. Dim regex As Regex = New Regex("[A-Z]{4}[0-8]{1}[0-9]{2}")
      2. Dim match As Match = regex.Match(TextBox1.Text)
      3. If match.Success Then
      4. TextBox2.Text = "is ok"
      5. End If


      klappt nicht. ich verstehe die Zusammensetzung trotzdem nicht ganz.
      ~Wir leben zwar alle unter dem gleichen Himmel, aber es haben nicht alle den gleichen Horizont~
      Hi,

      was bedeutet "klappt nicht" konkret? Sieht alles richtig aus und funktioniert auch (ich hab's getestet auf regex101.com/r/4iJufx/1 und in der IDE). Soweit ich sehe gibt es hier keinen Fehler.


      Link :thumbup:
      Hello World
      Ich bekomme immer das Ergebnis "ist ok"

      Bei COMP900A bekomme ich true zurück, Bei COMP250 auch, bei COMP900 auch.
      True dürfte es aber nur bei COMP250 und nicht bei COMP900A sowie COMP900 sein.

      Vollzitat entfernt. ~Thunderbolt
      ~Wir leben zwar alle unter dem gleichen Himmel, aber es haben nicht alle den gleichen Horizont~

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

      Ja aber das liegt doch nicht an deinem RegEx, der ist fehlerlos. Dein Code sagt zeige "ist ok" in Textbox2 an wenn der RegEx auf den String passt. Wenn der RegEx NICHT passt (wie bei "COMP900A") steht in der TextBox trotzdem immer noch "ist ok" wenn ein vorheriges Match erfolgreich war. Was dir fehlt ist lediglich eine zusätzliche else condition:

      VB.NET-Quellcode

      1. Dim regex As Regex = New Regex("[A-Z]{4}[0-8]{1}[0-9]{2}")
      2. Dim match As Match = regex.Match(TextBox1.Text)
      3. If match.Success Then
      4. TextBox2.Text = "is ok"
      5. Else
      6. TextBox2.Text = "DAS PASST NICHT!"
      7. End If


      Das war's schon. Dir ist es nicht aufgefallen weil du vermutlich immer zuerst einen String eingegeben hast wo das Match erfolgreich ist.


      Link :thumbup:
      Hello World

      Link schrieb:


      VB.NET-Quellcode

      1. TextBox2.Text = "DAS PASST NICHT!"



      OMG. Das ist nie passiert. Besten Dank für die Auflösugn dieser Braindead Frage.
      ~Wir leben zwar alle unter dem gleichen Himmel, aber es haben nicht alle den gleichen Horizont~

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