Regex mit und ohne und ohne mit :)



  • Die Suchmaschine hat mich hergetragen und ich hoffe auf Hilfe für diese Regex:

    Erstes Zeichen muss ein großer Buchstabe sein
    ^[A-Z]$

    dann können nur kleine Buchstaben und Ziffern folgen
    ^[A-Z][a-z0-9]$

    Punkt, Minus und Unterstrich könnte man mal mitnehmen
    ^[A-Z][a-z0-9_-.]$

    Und jetzt weiß ich ohne weitere Abfrage nicht weiter. Denn ich möchte:

    maximal vier Ziffern, egal wie verteilt ab Position 2
    maximal einen Punkt, einen Minusstrich, einen Unterstrich oder vielleicht doch besser:
    nur ein Sonderzeichen, egal welches! also Punkt, Minus oder Unterstrich.



  • Ich weiss nicht ob das mit Regexen sinnvoll möglich ist. Ich würde vermuten eher nicht.

    Was willst du denn machen und was sind die nicht-funktionalen Einschränkungen?

    Vielleicht wäre es ja möglich mit der Regex erstmal nur Kandidaten zu suchen, und die Kandidaten dann nachzufiltern?



  • Die Lösung für deine Probleme nennt sich Look-Ahead. Look-Aheads haben 0 Länge, du kannst also mehrere davon an derselben Stelle haben.

    Für die max. 4 Ziffern:
    ^[A-Z](?=(\D*\d?){4}\D*$)[a-z0-9_.-]+$

    Beachte auch noch, dass das - in eckigen Klammern speziell ist. Ich würde also nicht [_-.] schreiben (auch wenn das vielleicht geht, weil _ kleineren Code als . hat), sondern setzte das - als letztes Zeichen vor die ] oder escape es.

    Das $ matcht auch vor Newlines. Willst du stattdessen vielleicht lieber \Z? Und ggf. statt ^ ein \A (kommt auch auf den Regex-Dialekt und die Multiline-Switches an).



  • @hustbaer Es ist mit regulären Ausdrücken nicht möglich, aber die meisten Regular Expressions können heutzutage mit Lookahead/Lookbehind mehr ausdrücken als nur reguläre Ausdrücke.

    MfG SideWinder



  • @SideWinder Interessant. Ich kenne zwar die Begriffe Lookahead/Lookbehind, aber so wirklich verstanden was man damit machen kann hab ich nie. Bin froh drum, denn zuviel mit Regexen zu machen verbiegt einem glaub ich das Gehirn.

    Geht damit dann auch die Kombination die der/die OP haben möchte? Also die Kombination "max. 4 Ziffern" mit "max eins aus dem Set (Punkt, Minus, Unterstrich)".



  • @hustbaer Klar geht die Kombi.

    Ich hatte heute früh ein Beispiel geschickt.

    Der Bereich mit (?= ....) ist der Look-Ahead. In diesem konkreten Fall:
    ^[A-Z] matche einen Großbuchstaben (und konsumiere diesen)
    (?= ...) matche den ...-Teil an der aktuellen Stelle, konsumiere diesen aber nicht (das wollte ich mit "Länge 0" ausgedrückt haben)
    [a-z0-9_.-]+$ dann matche und konsumiere ab der aktuellen Stelle (also immer doch dieselbe wie vor dem Look-Ahead) die angegebenen Zeichen bis zum Ende.

    ... ist (\D*\d?){4}\D*$ - also (keine Ziffer beliebig oft, dann eine Ziffer 0 oder 1 mal)-4fach, dann noch beliebige nicht-Ziffern

    Da der Look-Ahead nichts konsumiert, kann ich an die Stelle einfach noch einen Look-Ahead setzen, um die Bedingung "maximal einen Punkt" zu erfüllen:
    (?=[^.]*\.?[^.]*$) - also keinen Punkt beliebig oft, dann möglicherweise ein Punkt und wieder beliebig viele nicht-Punkte
    Analog könnte man dann auch noch "maximal einen Minusstrich" implementieren.

    Stattdessen soll es ja "nur ein Sonderzeichen" sein. Da ist mir nicht klar, ob mit "nur ein" auch "maximal ein" wie davor gemeint ist oder "genau ein". Für "maximal ein" hätten wir also:
    (?=[^._-]*[._-]?[^._-]*$)

    Zusammen mit max 4 Ziffern und max einem Sonderzeichen:
    ^[A-Z](?=(\D*\d?){4}\D*$)(?=[^._-]*[._-]?[^._-]*$)[a-z0-9_.-]+$

    In Perl kann man REs zum Glück mit /x schreiben und damit zwischendrin Whitespace und Kommentare einfügen 🙂



  • @wob
    Aaaah, OK. Mir ist erst jetzt das "$" in deinen Lookahead-Dingsen aufgefallen. Ich glaub dann hab ich's so ca. verstanden.
    Also das Lookahead Dings sagt entweder "ab hier muss was kommen was X matcht" bzw. bei negativem Lookahead halt "ab hier darf X auf keinen Fall matchen".

    Ist für mich aber immer noch schrecklich 🙂 Vor allem wenn man dann anfangen muss das Zeug auf Performance zu optimieren. Da schreib ich mir lieber meine Charakter-wusel-Schleife. Bei der weiss ich dann dass sie immer O(N) ist.



  • @hustbaer ja, hast du richtig verstanden. Es gibt außerdem noch die Look behinds, womit man gucken kann, ob etwas vor der aktuellen Position steht.
    Generell kann man Backtracking manchmal noch wegoptimieren, in Perl mit (>?...). Denn du hast recht, man kann auch leicht REs mit exponentiellem Zeitbedarf bauen, besonders mit Sternen....

    Und sowas wie countDigits(str) <= 4 ist leichter zu lesen.



  • @wob sagte in Regex mit und ohne und ohne mit 🙂:

    ^[A-Z](?=(\D*\d?){4}\D*$)(?=[^._-]*[._-]?[^._-]*$)[a-z0-9_.-]+$

    Ist Regex eigentlich offiziell Write-Only?
    Ich hoffe es. 🤒


  • Mod

    @Swordfish sagte in Regex mit und ohne und ohne mit 🙂:

    @wob sagte in Regex mit und ohne und ohne mit 🙂:

    ^[A-Z](?=(\D*\d?){4}\D*$)(?=[^._-]*[._-]?[^._-]*$)[a-z0-9_.-]+$

    Ist Regex eigentlich offiziell Write-Only?
    Ich hoffe es. 🤒

    Der Regex-Erklärer. Oder mit mehr Text statt Bildchen, aber ohne dass ich wüsste, wie man einen bestimmten Ausdruck verlinken kann: https://regexr.com/



  • @wob sagte in Regex mit und ohne und ohne mit 🙂:

    Und sowas wie countDigits(str) <= 4 ist leichter zu lesen.

    Das schreib ich ja sowieso, unabhängig davon wie countDigits implementiert ist (Regex-Impl oder Selbst-Geparsed)

    MfG SideWinder



  • BTW: Wer sich für regular expressions detaillierter interessiert, in den knapp 550 Seiten von https://www.amazon.de/Mastering-Regular-Expressions-Jeffrey-Friedl/dp/0596528124/ steigt man echt zum Profi auf und hat auch keine Probleme mehr performante Expressions zu kreieren, nicht nur weil viele gute Tipps drin sind, sondern weil man lernt wie der Implementierungs-Ansatz verschiedener Engines ist. Sehr spannendes Buch, kanns nur weiterempfehlen 🙂

    MfG SideWinder



  • @SideWinder sagte in Regex mit und ohne und ohne mit 🙂:

    und hat auch keine Probleme mehr performante Expressions zu kreieren

    Ähm. Ich würd jetzt mal vorsichtig behaupten dass das gar nicht immer möglich ist. Also wenn man es mit einer handgeschriebenen Lösung bzw. halt dem theoretischen Maximum (an Performance, nicht Laufzeit ;)) vergleicht.

    ps: Vor allem finde ich es immer schade wenn man eine Deskriptive Syntax verwendet und sich dann trotzdem Gedanken darüber machen muss wie die Engine es implementiert. Speziell wenn dann oft die einfachste Variante es zu schreiben die schlechteste ist. Andrerseits ist das bei SQL auch nicht viel anders, und SQL mag ich. Kommt halt auch immer darauf an wie gut man sich mit etwas auskennt und wie wohl man sich daher damit fühlt.


  • Mod

    Das wichtigste ist erst einmal, dass man nicht versehentlich etwas schreibt, dass dann beim Auswerten exponentiell explodiert. Das passiert schnell, wenn man sein Anfängerwissen naiv auf das erste verschachtelte Problem los lässt. Wenn man das zu vermeiden weiß, hat man schon einmal viel gewonnen.



  • @SeppJ
    Ernst gemeinte Frage, da ich mich mit Regexen kaum auskenne: kann man das so einfach vermeiden? Also ... was ich meine: kann man mit etwas Übung/Hintergrundwissen wirklich zuverlässig (und schnell) beurteilen dass die Laufzeit nicht explodiert?


  • Mod

    @hustbaer sagte in Regex mit und ohne und ohne mit 🙂:

    @SeppJ
    Ernst gemeinte Frage, da ich mich mit Regexen kaum auskenne: kann man das so einfach vermeiden? Also ... was ich meine: kann man mit etwas Übung/Hintergrundwissen wirklich zuverlässig (und schnell) beurteilen dass die Laufzeit nicht explodiert?

    Das müsstest du @SideWinder fragen. Ich weiß nur genug, um dir hinterher sagen zu können, warum etwas explodiert ist 🙂


Anmelden zum Antworten