Hallo zusammen. Ich versuche gerade schon eine Weile mit Hilfe von Google folgendes zu realisieren:
Ich habe folgenden String:
"HALLO .W"
Folgendes ist zu prüfen:
- Die Größe des Strings müssen genau 9 Zeichen sein
- Die Letzten beiden Zeichen müssen immer .W sein
- Das Erste Zeichen muss [A-Za-z0-9] sein
- Dazwischen dürfen 6 mal [A-Za-z0-9] oder Leerzeichen sein
--> wobei nur am Ende (also vor dem Punkt) Leerzeichen erlaubt sind
--> und nicht zwingend ein Leerzeichen dabei sein muss
Beispiel für erlaubt:
"HALLO .W"
"H .W"
"HALLO12.W"
Beispiel für verboten:
" HALLO.W"
"H.W"
Das kann doch eigentlich nicht so schwer sein, aber ich komme leider nicht drauf.
Ich weiß z.B. nicht wie ich definieren kann, dass ich beliebig viele Leerzeichen haben darf, aber diese nur am Ende stehen dürefen.
Hat vielleicht jemand von den RegEx Cracks einen Tipp für mich?
Beliebig viele Leerzeichen: \s*
Oder einfach ein Leerschritt anstelle von \s
Regex erlaubt das, würde ich aber unter Umständen von absehen, da man diese Toleranz auch aus stellen kann.
Dass diese Leerzeichen nur vor dem ".W" am Ende erlaubt sind:
Du baust den Teil des Patterns vorher so wie gewollt und schreibst am Ende das "\s*\.W" ein und fertig
Vergiss nicht "^" am Anfang und "$" am Ende zu schreiben, das stellt sicher, dass der gematchde String auch der ganze String ist. Voraus gesetzt, Du willst das überhaupt
Ein Tipp noch: https://regex101.com/
Ist sehr hilfreich, wenn Du mit Regex arbeitest
Da kannst Du auch mit STRG+S speichern und bekommst dann einen Link, der immer mit dem Pattern und dem Text ausgestattet ist, was zu dem Zeitpunkt drin stand.
PS:
Auf die Länge würde ich per Code (myString.Length == 9) prüfen, ist mit Abstand das Einfachste.
In Regex geht das bestimmt auch, aber ist das wirklich notwendig?
PPS:
In regex101, wenn Du da mehrere Zeilen im Text auf einmal prüfen willst, musst Du vorher in den Regex-Flags (rechts vom Pattern) auf MultiLine stellen. Ansonsten prüft er immer den kompletten Text (mit Zeilenumbrüchen), das passt dann natürlich nicht
PPPS:
Schau dir mal "\w" an, das entspricht "[a-zA-Z0-9_]", beachte den Unterstrich, der am Ende mit drin steht.
Wenn das in Frage kommt, würde ich eher zu dem raten, weil das die doch recht unübersichtlichen Regex-Patterns mMn. etwas übersichtlicher gestaltet.
Dieser Beitrag wurde 4 mal editiert, zum letzten Mal von Palladin007 am .
klar geht das, z.B. mit einem look ahead gleich am Anfang:
^(?=.{9}$)
Zitat
... aber ist das wirklich notwendig?
Das kann in bestimmten Fällen durchaus nötig sein, insbesondere immer dann, wenn Pattern erst zur Laufzeit von Außen kommt (z.B. per Benutzereingabe oder aus einer Datei).
Hallo HiJack82,
was genau ist denn dein Problem? Du hat ja sehr genau beschrieben, was du machen willst. Das kannst du im Grunde 1:1 in Regex umsetzen, nötigenfalls mit Hilfe von [Artikel] Regex-Tutorial. Die einzige Klippe ist das mit der Länge, für die jetzt zwei Lösungen bekommen hast.
dass das geht, weiß ich, aber wenn's nicht zwingend notwendig ist, würde ich das nicht tun.
Gerade wenn Regex nur eine lokale Hilfe im Code sein soll, dann würde ich eher per Length prüfen.
Außerdem kommt hier gleich eine weitere "Komplexitäts-Stufe" (Wegen Lookahead) dazu kommt, die viele (Anfänger) noch nicht kennen/verstehen.
Vermutlich ist es auch besser, einfache Patterns nicht mit Regex zu prüfen.
Das kann schneller sein, hauptsächlich verbessert es aber die Wartbarkeit, besonders, wenn im Laufe der Zeit jemand daran arbeiten muss, der Regex nicht fließend spricht.
Darf ich mir auf der Arbeit auch manchmal anhören, weil ich das Eine oder Andere mal relativ komplexe Regex-Patterns eingebaut habe :D
Wenn das nicht anders geht (z.B. wenn es aus der Config kommt), dann sieht das natürlich anders aus.
Was nun der beste Weg ist, kann wohl nur HiJack82 zuverlässig entscheiden.
In dem Sinne der Wink zu HiJack82:
Ist Regex überhaupt notwendig?
Das Pattern lässt sich auch sehr einfach direkt in Code prüfen.
Ich kenne es z.B. bei mir, dass ich mir manchmal auf die Finger hauen muss, dass ich Regex an der Stelle eigentlich gar nicht brauche :D
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Palladin007 am .
Das kann schneller sein, hauptsächlich verbessert es aber die Wartbarkeit
meine Erfahrung ist genau andersherum. Bei mir war Regex nicht nur deutlich leichter und schneller zu erstellen, sondern auch flexibler und immer deutlich leichter wartbar, gerade wenn die Aufgabe komplexer ist. Auch bei meiner Aufgabe im Programmierspiel kam dN!3L in seiner abschließenden Lösung zu einem ähnlichen Fazit:
Zitat von dN!3L
Wenn ich den Aufwand der ganzen Nacharbeiten noch mit dazurechne, sind reguläre Ausdrücke eindeutig einfacher erstellt und man findet Fehler schneller.
Ich persönlich habe noch an keiner einzigen Stelle bereut, Regex eingesetzt zu haben, egal wie einfach oder komplex die Aufgabe war, ganz im Gegenteil.
Man darf auch nicht vergessen, dass ein Pattern nur dann komplex wird, wenn die Komplexität schon in der Aufgabe steckt und dann ergibt auch das Ausprogrammieren komplexen - und meiner Erfahrung nach eben sogar noch komplexeren - Code.
Aber auch hier gilt: Wir haben unsere Meinungen und Erfahrungen geteilt. Entscheiden muss HiJack82.
herbivore
PS: Wenn man die Lesbarkeit von Pattern für komplexere Aufgaben erhöhen möchte, gibt es zwei gute Möglichkeiten. Zum einem kann man Pattern per RegexOptions.IgnorePatternWhitespace nicht nur mit Leerzeichen und Zeilenumbrüchen strukturieren und damit deutlich lesbarer machen, sondern mit # sogar beliebige Kommentare einfügen. Zum anderen kann man die einzelnen Teilpattern ganz simpel in einzelne, sprechend benannten Variablen speichern und daraus erst am Schluss den Gesamtpattern (z.B. mit String) zusammenbauen. Auch hier entsteht der die Lesbarkeit fördernde Effekt vor allem durch die Kombination von Strukturierung und Kommentierung.
erstmal vielen lieben Dank für all die Mühe. Es ist aber leider noch nichts passendes dabei.
\s* kann ich ja nicht verwenden, weil ich nicht beliebig viele Leerzeichen zulassen kann.
Ich versuche nochmal mein Kernproblem besser zu beschreiben.
- Der gesamte String darf aus 9 Zeichen bestehen.
- Die letzten beiden müssen immer .W sein
- Das erste muss \w sein (danke Palladin00)
--> Jetzt kommt das eigentliche Problem:
Jetzt sind noch 6 Zeichen in der Mitte übrig.
\s* darf ich nicht machen weil nicht beliebig viele Leerzeichen vorkommen dürfen
\s{n} kann ich auch nicht machen, weil ich n nicht kenne.
Das Problem ist also, dass ich 6 Zeichen habe die mit \w anfangen und eventuell (muss nicht sein) mit \s enden. Ich weiß nicht wie viele Zeichen und wie viele Leerzeichen da kommen. Ich weiß nur, dass es an der Stelle insgesamt 6 sind und Leerzeichen nur am Ende erlaubt sind. Sorry, aber das ist echt schwierig zu erklären.
@Palladin007: Eigentlich ist RexEx nicht notwendig. Aber ich bewundere das Problem :-) und bin extrem neugierig ob das mit RegEx überhaupt lösbar ist.
@Herbivore: Mein Problem ist, dass ich die ganzen Tutorials bereits gelesen habe, mein Problem damit aber nicht lösen kann.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von HiJack82 am .
die Lösung mit dem Problem der festen Länge habe ich oben bereits geschrieben. Wenn du den look ahead Pattern an den Anfang deines Pattern schreibst, dann ist sichergestellt, dass der String insgesamt genau 9 Zeichen hat und dadurch kannst du an der fraglichen Stelle einfach + bzw. * verwenden.
Du brauchst nicht zwangsläufig Gruppen nutzen, die erhöhen nur die Anzahl Klammern, in deinem konkreten Fall hast Du aber keinen Vorteil dadurch.
Der einzige Fall, wo es wirklich notwendig ist, ist die Kombination von \w ODER \s
Das aber nur als Tipp, an der Funktion sollte das nicht viel ändern
Du machst immer noch den Fehler, dass Du nicht die Länge von 0 bis 6 prüfen solltest. Du sagst doch selber, dass Du diese Länge gar nicht weist.
Was Du tust: Du verlangst einmal \w und danach entweder \w oder \s in beliebiger Reihenfolge und maximal 6 mal.
Gebe vor, dass vorne mindestens einmal \w (danach beliebig oft, schau dir das + an) und danach beliebig oft \s stehen darf - gefolgt durch die zwei Schluss-Zeichen. Dieses Pattern würde deine Regeln befolgen, außer die feste Länge.
Erst dann kümmerst Du dich um die Gesamtlänge von 9 Zeichen, indem Du das mit einem Lookahead prüfst.
PS:
Im Code-Tag kannst Du nicht fett markieren :P
Ich würde den Code-Tag weg lassen, Regex wird sowieso nicht formatiert und bekommt auch kein Highlighting
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von Palladin007 am .
Vielen Dank Paladin007. Deine Tipps sind wirklich sehr hilfreich!
Die Klammern habe ich noch drin, weil man so im https://regex101.com/ schön die resultate der einzelnen Gruppen sieht. Das hätte ich dann später auch wieder entfernt.
Zitat
Was Du tust: Du verlangst einmal \w und danach entweder \w oder \s in beliebiger Reihenfolge und maximal 6 mal.
Jetzt kommen wir der Sache schon näher. Das kann ich so nicht benutzen. Wenn ich nach \w 6 mal \w oder \s zulasse würde ABC DEF.W auch akzeptiert werden. Das darf ich aber nicht akzeptieren.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von HiJack82 am .
@herbivore:
Das war auch mein erster Gedanke. Das ist leider falsch.
Diese Abfrage würde "ABC DEF.W" erlauben. Leerzeichen dürfen aber nur am Ende und vor dem .T vorkommen (müssen aber nicht).
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von HiJack82 am .
\w+\s*\.W erlaubt:
Mindestens ein \w, kein Leerzeichen
Danach beliebig oft \s
Zum Schluss die Zeichenkette ".W"
Das ist genau das, was Du haben willst, genau das hast Du im Eingang geschrieben.
Es wurde ja schon mehrfach geschrieben: Ignoriere die Länge, das tut der Lookahead
Hier ein regex101-Link: https://regex101.com/r/DwYZ6F/1
Da ist (fast) das Pattern, was Sir Rufo auch gepostet hat, einzig das $ fehlt im Lookahead.
Über dem Pattern gibts ein graues v1 mit Pfeil, klick darauf und Du bekommst auch eine zweite Version angeboten.
Die ist mMn. etwas unschöner, aber vielleicht hilft es um Lookaheads besser zu veranschaulichen.
Diese zweite Version dreht die Funktion vom Lookahead um.
Das "eigentliche" Pattern .{9} prüft, dass es 9 beliebige Zeichen gibt und der Lookahead prüft mit \w+\s*\.W deine Regeln.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Palladin007 am .
Ich möchte eigentlich nur HELLO .W auf die Länge von 9 Zeichen prüfen. Das funktioniert aber mit meiner oben gezeigten Expression noch nicht richtig. Muss ich da noch ein $ setzten, oder?
Übrigens, das ^ bei START habe ich drin, weil START der erste String in der Zeile ein muss. Ohne dieses Zeichen werden führende Leerzeichen akzeptiert. Das möchte ich aber nicht. Habe ich das dann so richtig gemacht?
Es ist doch immer am besten einfach die Lösung hinzuschreiben.
nö, das Forum ist kein Pattern-Generator. Du beschäftigst dich ja mit dem Lösungsweg, wie man an deinen Antworten sieht. Andere tun das nicht und wollen nur andere Leute einspannen, um ohne eigenen Aufwand eine funktionierende Lösung zu bekommen. Deshalb posten wir eben gerade *nicht* einfach eine fertige Lösung.
Zitat
Jetzt habe ich noch ein Problem mit dem gesamten Ausdruck
Wenn vor und nach dem (Teil)String mit 9 Zeichen noch was anderes steht, dann funktioniert der Look Ahead so natürlich nicht. Der geht ja davon aus, dass von Beginn bis Ende des String (bzw. der Zeile) nur 9 Zeichen stehen.
Aber natürlich kann man den Look Ahead auch so ändern, dass er nach einem Muster einer bestimmten Länge sucht, also z.B. das was du oben (fast) geschrieben hast (leicht geändert):
(\w|\s){7}(\.W)
Nur eben in den Look Ahead gepackt. Der Look Ahead sorgt dann wieder für die richtige Länge, diesmal eben von sieben(!) Zeichen (Buchstaben oder Leerzeichen). Für die richtige Reihenfolge von \w+ und \s* sorgt dann wieder der eigentliche Pattern.
Andere tun das nicht und wollen nur andere Leute einspannen, um ohne eigenen Aufwand eine funktionierende Lösung zu bekommen.
Da hast Du natürlich schon recht. Aber schau mal, wie wenig Fragen ich in der langen Zeit im Forum gestellt habe. Ich gehe in der Regel immer wie folgt vor:
- vorhandene Bücher
- Google
- Foren lesen
--> Frage im Forum stellen
Manchmal steht mal halt auch bei vermeintlich einfachen Dingen so richtig auf dem Schlauch...
So wie auch ich leider immer noch :-(
Ich habe jetzt folgende Expression:
\b^START\s\b(?=(\w|\s){7})\w+\s*\.W(\s)(\bEND\b|\bFINISH\b)
Die Funktioniert bis auf eine Ausnahme (hoffe es ist wirklich nur eine). Der Teilstring "HELLO .W" darf bei mit mindestens 9 Zeichen lang sein. Die maximale länge wird aber scheinbar nicht richtig geprüft. Hat jemand eine Idee, was ich an meinem Ausdruck noch verbessern kann?
es reicht natürlich nicht (\w|\s){7} in den Look Ahead zu schreiben. Das fordert ja nur, dass mindestens 7 Zeichen vorhanden sind. Es muss auch noch der Teil in der Look Ahead, der das Ende dieser 7 Zeichen markiert, also mindestens der Punkt (\.). So wie ja vorher auch das $ mit im Look Ahead stand.