Der 'Like'-Operator, eine nützliche kleine RegEx.IsMatch-Alternative

    • VB.NET

      Der 'Like'-Operator, eine nützliche kleine RegEx.IsMatch-Alternative

      Ein ziemlich nützlicher, aber dennoch unbekannter bzw. selten genutzter Operator, ist der 'Like'-Operator.
      Er ähnelt auf den ersten Blick ein wenig RegEx, im Grunde genommen ist er auch ein wenig ähnlich, aber er kann nicht so viel...

      Wann wird dieser Operator verwendet?
      Es gibt natürlich verschieden Anwendungsmöglichkeiten. Der Operator überprüft einfach eine Zeichenfolge mit einem bestimmten Muster (wie man es auch aus RegExp kennt).

      like = so wie auf gut deutsch gesagt. Also wird geprüft, ob die angegebene Zeichenfolge so wie das Muster aussieht.
      Der 'Like-Operator' nimmt einem manchmal viel Arbeit weg. Besonders an Stellen, an denen man mit regulären Ausdrücken arbeiten könnte. Mit regulären Ausdrücken ist es auch komplizierter auszuwerten und verliert bei komplizierten Ausdrücken an Übersichtlichkeit. Es sei jedoch gesagt, dass der Operator kein RegEx ist und somit keine ganzen Inputs prüfen kann, sondern sozusagen nur bestimmte Unterschiede in Strings und da isses dem OP dann wurscht, ob er ein oder zwei Buchstaben mehr findet... Das ist damit gemeint. Also na klar, man kann ganze Inputs prüfen, aber es wird nicht jede weitere Änderung beachtet! Dies ist dann vom Muster abhängig:

      Beispiel

      Nehmen wir mal ein kleines Beispiel. Wir möchte prüfen, ob ein Zeichen eines Strings nur Buchstaben von A-D enthält.

      VB.NET-Quellcode

      1. Dim input = "E"
      2. If Not input Like "[A-D]" Then
      3. MessageBox.Show("Der Input '" & input & "' und der angegebene Pattern stimmen nicht überein."
      4. End If


      So, wir haben hier einfach einen Input 'E' und prüfen dann mit dem Like-Operator, ob dieser dem angegebenen Pattern gleicht, also ob nur die Buchstaben von A-D enthalten sind. Übrigens spielt hier Groß-und Kleinschreibung ebenfalls eine Rolle, sodass bei Beachtung der Pattern [a-dA-D] lauten müsste. Da jeder natürlich sofort sieht, dass hier das Ergebnis 'False' ist, habe ich in die If-Abfrage gleich noch ein 'Not' gepackt, da es sinnlos wäre extra noch ein 'Else' hinzuzufügen, wenn eh nie 'True' rauskommen kann. Nun soweit dazu.

      Ausgabe: Der Input 'E' und der angegebene Pattern stimmen nicht überein.

      Die Einzelteile

      Der Like-Operator besteht aus 3 Teilen:

      result Ein boolscher Wert, der zurückgegeben wird, wenn Input und Pattern gleich bzw. nicht gleich sind. (Wenn beides leer ist wird 'True' zurückgegeben.)
      string Ein beliebiger Input zum Abgleichen
      pattern Das Muster für den Vergleich

      Alle diese Teile sind natürlich erforderlich.


      Die verschiedenen Muster und Zeichen


      • Zeichen: *
        Beschreibung: Findet 0 oder mehrere Zeichen
        Beispiel: A*A gibt 'True' für ABBA zurück, aber auch für ABBBA oder AFA oder auch nur AA
        Aber warum AA? Ganz einfach. Es findet 0 oder mehrere Vorkommen.

      • Zeichen: ?
        Beschreibung: Ein beliebiges einzelnes Zeichen
        Beispiel: Ha?s gibt 'True' für Hans zurück, aber auch für Haas oder Hals. Bei Has wird der Operator jedoch failen. Warum? '?' Erwartet ein Zeichen. Es ist keines vorhanden, sodass dann der Input nur noch 3 Zeichen hat. Da in diesem Falle an 4. Position ein 's' erwartet wird, jedoch dann keines vorhanden ist wird der Like-Operator "False" zurückgeben.
        Der Match failt also, weil der Eingabestring kürzer ist als der Pattern erwartet.

      • Zeichen: #
        Beschreibung: Eine beliebige Ziffer in der Charlist von 0-9 oder auch in Schreibform: [0-9]
        Beispiel: Form# gibt 'True' für Form1 zurück, aber auch für Form4 oder sogar Form0.





      So, das sind die einzelnen Zeichen der Patterns. Jetzt kommen wir zu den Gruppen bzw. man nennt sie auch Charlists.
      So eine haben wir auch oben schon benutzt. Also das ist nicht schwer.

      • Bezeichnung: [charlist]
        Beschreibung: Ein beliebiger angegebener Raum für Zeichen (eine Zeichenliste, bzw. eine Gruppe)
        Beispiel: *[a-z]* gibt 'True' für aae zurück, aber auch für 000eeee, da die letzten Zeichen Buchstaben von a-z enthalten. Jedoch nicht für 000EEEE, da dort Großbuchstaben enthalten sind. Wenn diese mit rein sollen, dann muss der Pattern so lauten:
        *[a-zA-Z]*

        Dies macht folgendes: Prüfe, ob eines der möglichen Zeichen 1 mal oder mehr im Input vorkommt.



        *[charlist] - Zeichenkette endet mit einem Buchstabe in [charlist]
        [charlist]* - Zeichenkette beginnt mit einem Buchstabe in [charlist]
        *[charlist]* - Zeichenkette enthält mindestens einen Buchstabe aus [charlist]
        [charlist] - Zeichenkette enthält ein einziges Zeichen das mit einem aus [charlist] übereinstimmt


        Beispiel:

        VB.NET-Quellcode

        1. "EEEAA" Like "*[A-D]*" = True
        2. "EEEaa" Like "*[A-D]*" = False
        3. "AA" Like "*[A-D]*" = True
        4. "AEE" Like "[A-D]*" = True
        5. "EAA" Like "[A-D]*" = False
        6. "EAA" Like "*[A-D]" = True
        7. "AEE" Like "[A-D]*" = False
        8. "E" Like "[A-D]" = False
        9. "A" Like "[A-D]" = True
        10. "AA" Like "[A-D]" = False


        Danke an @xtts02: fürs Testen!

      • Bezeichnung: [!charlist]
        Leute, die viel mit C# arbeiten werden jetzt schon wissen was dieser Pattern macht.
        Beschreibung: Ein beliebiger angegebener Raum für Zeichen (eine Zeichenliste, bzw. eine Gruppe) , die nicht enthalten sind
        Beispiel: *[!a-zA-Z]* gibt 'True' für 007 zurück, aber auch für Test2. Jedoch nicht für Test, da dort keine Zahl enthalten ist.
        Wichtig ist, dass das '!' in die eckigen Klammern muss, sonst fragt es sich selbst ab bzw. ob da ein "!" ist.





      So, das war doch garnicht so schwer...
      Jetzt folgt noch, wie man Sonderzeichen abfragt (?, [, ], #) usw.

      Dazu müssen wir das Zeichen in Klammern setzen. Wenn wir Klammern selbst abfragen wollen dann so:
      '(()'
      In diesem Fall wird abgefragt, ob ein ( enthalten ist.
      Bei '(])' wäre das dann ein ]...

      Ist also auch nicht schwer. Allerdings kann man in einer Zeichenliste bzw. Gruppe nicht nach ']' fragen, da ja dieses Zeichen bereits verwendet wird, um Gruppen zu erstellen bzw. hier abzuschließen.
      Wir können also auch nicht einfach nach einer leeren Zeichenfolge mit '[]' in einer Gruppe suchen, eben wegen diesem Problem. ('[]' würde übrigens also null bzw. "" ausgeben. Dazu müssten wir dann den Like-Operator 2 mal verwenden. Dazu findet Ihr aber hier mehr.

      Ok. Zeichenbereiche in Gruppen bzw, Zeichenlisten werden einfach mit einem Bindestrich (-) festgelegt. Also A-Z sind alle Buchstaben von A-Z. Ist also ein Bereich, der A, B, C... Z umfasst.
      Die Reihenfolge ist allerdings wichtig, sodass A-Z gültig ist, aber Z-A jedoch nicht. Es muss immer in chronologischer Reihenfolge sein.

      Mehrere Zeichenbereiche werden nicht mit Leerzeichen getrennt. So haben wir es auch oben bei Groß- und Kleinschreibung gemacht. Also a-zA-Z oder A-DE-H. Nicht gültig ist zum Beispiel sowas: a-z A-Z.

      Die Sortierreihenfolge
      Diese ist von der Einstellung 'Option Compare' abgängig.
      Option Compare Binary (Standard) findet für A-E:
      A, B, C, D und E.
      Option Compare Text findet für A-E:
      A, a, À, à, B, b, C, c, D, d, E und e.

      Es wird dann also auch Groß und Kleinschreibung, sowie andere Zeichen beachtet.

      Digraphzeichen
      In manchen Sprachen, z. B. Französisch gibt es Zeichen, die zwei Buchstaben auf einmal implementieren. Beispielsweise Schwester: Sœur
      Da ist dieses 'oe'.

      Das sind Diagraphzeichen. Der Like-Operator ist schlau und erkennt sowas und wird es dann zu solch einem Zeichen zusammenschließen.

      Okay, das war der Like-Operator. Ich hoffe es finden sich nun ein paar Leute, die diesen verwenden werden, da er eine echt gute und kurze Alternative zu RegEx.IsMatch ist.

      lg Trade

      PS: Hier noch der Link zur Doku auf MSDN: msdn.microsoft.com/de-de/library/swf8kaxw(v=vs.90).aspx
      #define for for(int z=0;z<2;++z)for // Have fun!
      Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

      Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

      Dieser Beitrag wurde bereits 27 mal editiert, zuletzt von „Trade“ () aus folgendem Grund: Fehler bei Pattern und Verbesserungen