Regex

  • Sonstige

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von Link.

    Hallo,

    hab ne Frage zur Validierung einer TextBox, in die ich ein Polynom schreibe, etwa der Art:

    2x^5-2,6x^4+3/7x^3-5*x^2+x-13 (das *-Zeichen kann oder auch nicht gechrieben werden-beides möglich)

    es kommen darin also nur die Zeichen: (0-9) und (x ^ + - / *)

    Nun krieg ich es in Regex nicht zusammen:

    Dim sPattern As String = "...???..."

    If Not System.Text.RegularExpressions.Regex.IsMatch(txtPolynomDivisionNenner.Text, sPattern) Then
    MsgBox("Die Syntax der Polynomeingabe ist nicht korrekt!")
    Exit Sub
    End If

    Wie muss sPattern aussehen?

    Könnte mir da, bitte, jemand großherzig helfen und die Syntax dafür schreiben?

    Danke

    hybernate5
    Ausm Kopf würde ich es folgendermaßen machen (nicht getestet!): (\d+(,\d+)?\*?x\^\d+)((\+|-)(\d+(,\d+)?\*?(x\(^\d+)?)?))*

    Edit:
    Habs mal getestet und ich hatte wohl noch ein paar kleinere Fehler drin. So funktioniert es (habe zumindest keinen String finden können, welcher nicht gematcht werden konnte):
    ^((\d+(,\d+)?\*?)?(x(\^\d+)?)?)((\+|-)((\d+(,\d+)?\*?)?(x(\^\d+)?)?))*$
    Viel Spaß :)

    Edit 2:
    So geht es glaub ich sogar mit einer beliebigen Variable (es muss dann jedoch durch den gesamten Term hindurch die gleiche verwendet werden - sonst wäre es ja kein Polynom mehr):
    ^((\d+(,\d+)?\*?)?((?<var>[a-z])(\^\d+)?)?)((\+|-)((\d+(,\d+)?\*?)?(\k<var>(\^\d+)?)?))*$

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

    Hab' verdammt vielen Dank,

    habs probiert, leider wird mir ein Fehler angezeigt: "Zu viele )-Zeichen", heißt es?

    Zum Verständnis:
    Die Polynome sind unterschiedlich lang.
    Es kommt nur auf das Vorkommen bestimmter Zeichen an und keiner Anderen.

    Also muss es ein allgemeiner/-es Filter sein, wobei auch ein ganz kurzes Polynom zugelassen ist, nämlich: x,
    also ein x muss mindestens drin sein. Zahlen und die übrigen Zeichen, aus dennen sich das Polynom zusammensetzt, dürfen also vorkommen, müssen aber nicht, wie im Fall von: x.
    Natürlich ist es ziemlich witzlos mit x zu arbeiten und so haben die Polynome verschiedene Grade.
    Beispiele:
    x^6-23x^2-55
    oder
    x^4-2/3x^2+2*x^-12
    oder
    2/7*x^4-2x^3+3/5x^2-x+5
    oder
    x^11-3x^9+12x^7+57/23x^6-6x^5+x^4-11*x^3+x^2-x-33

    Also es müsste etwas Allgemeines sein...?

    Nochmals vielen Dank für die Mühe.

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

    Habe deine Korrektur ausprobiert, alles bestens bis auf: x^2+2/3x+2
    Der Bruch 2/3 geht nicht...? leider.
    Kann man da noch das Divisionszeichen / einbauen? danke

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

    Ok, so gehen auch negative Zahlen und negative Exponenten (Brüche hab ich weggelassen, wenn die aber unbedingt benötigt werden, kann ich es auch noch hinzufügen):
    ^((-?\d*(,\d+)?\*?)?(x(\^-?\d+)?)?)((\+|-)((-?\d*(,\d+)?\*?)?(x(\^-?\d+)?)?))*$

    Und ja, mein Regex lässt schon die ganze Zeit die folgenden beiden ungewöhnlichen Polynome zu: 1, x ;)

    Nachtrag bzgl. deinem Nachtrag:
    @hybernate5
    Wenn es sein muss, sind natürlich auch Brüche möglich ^^
    ​^(((-?\d*(,\d+)?\*?)|\d+\/\d+)?(x(\^-?\d+)?)?)((\+|-)(((-?\d*(,\d+)?\*?)|\d+\/\d+)?(x(\^-?\d+)?)?))*$

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

    also es funktioniert, offenbar.
    Habs probiert.
    Wahnsinn!

    Ich muss dir sehr danken!!! Ds wa wirklich eine echte Hilfe!

    Das hätte ich nie geschafft!
    Wenn ich mir nur vor Augen halte, wie scheinbar einfach meine Fragestellung war und dann so ein komplexes Muster die Antwort ist...

    weshalb Brüche?
    ganze Zahl zB: 3=3/1
    Kommazahl zB: 2,5=25/10=5/2
    Bruch zB: 1/3=0,33333333333333333333333333333333333....usw? Ungenau. 1/3 ist genau, denn 0,3 Periode kann ich nicht genauer ausdrücken als mit 1/3.
    Deshalb wandle ich alles in Brüche um und rechne damit. Mit Brüchen erfasse ich nicht nur die gängigen Formen, sondern ich kann Zähler/Nenner getrennt in Integer-Variablen laden.

    Nochmals vielen Dank
    Und noch einen schönen Abend

    hybernate5
    Irgendwann werden solche Patterns zum Alltag, wenn man viel mit Regex arbeitet ^^ Ist halt wie eine eigene Programmiersprache für sich.
    Wenn du dich noch nicht allzu gut mit Regex auskennst, kannst du es zum Beispiel mit dem Regextester von Regex101 anschauen: regex101.com/r/mM9lB8/3 Da kann man rechts die einzelnen Teile der Expression "erklärt" bekommen. Sehr hilfreich könnte für dich auch Regexper sein - ein Tool, welches ein Diagramm zu einem Pattern generiert: regexper.com/#%5E(((-%3F%5Cd*(…-%3F%5Cd%2B)%3F)%3F))*%24.
    Das mit den Brüchen war nicht so gemeint - ich wunderte mich nur, da Brüche nicht gerade oft geparst werden müssen.

    Aber wie planst du, das alles zu parsen? Das Pattern überprüft doch bisher nur, ob der String ok ist.

    Viele Grüße
    Stefan :)

    nafets schrieb:

    Aber wie planst du, das alles zu parsen? Das Pattern überprüft doch bisher nur, ob der String ok ist.
    Das frage ich mich schon die ganze Zeit.
    Anstatt einen meterlangen Regex-Ausdruck zu erzeugen, hätte ich den Ausdruck einfach geparst.
    Da fällt die syntaktische Prüfung als Nebenprodukt ab.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

    petaod schrieb:

    Anstatt einen meterlangen Regex-Ausdruck zu erzeugen, hätte ich den Ausdruck einfach geparst.

    Man kann ja auch mittels des Regex-Patterns den Term parsen - es würde nur ein paar Modifikationen benötigen ^^
    Also meine Übungen mit Parser für mathematische Ausdrücke kommen auch zu ganz anderen Ergebnissen.
    Regex ist da nützlich um den Text in Token zu zerlegen, und dabei Klammern, Zahlen, Operatoren, Funktions-Aufrufe unterscheiden.
    Aber die Korrektheit des ganzen Strings kann Regex glaub nicht überprüfen.
    Die erweist sich erst, wenn man da tatsächlich rechen-operationen von generiert.
    Aus meim FormelParser der Regex:

    VB.NET-Quellcode

    1. Dim rgxToken As New Regex("(?<operator>[+\-*/^()])|(?<constant>[\d\.]+)|(?<func>\w{2,})|(?<param>[a-z])")
    Der matcht auf jedes einzelne Token und fällt eine Typ-Unterscheidung, aber Syntax-Fehler kriegt der ühaupt nicht mit.

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

    @nafets

    mein Code steht schon und arbeitet. Hab die Division und Multiplikation gemacht.
    Nur im Nachhinein wollte ich die Eingaben gegen das Vertippen absichern. Da verfiel ich eben auf Regex.

    Was mir gerade einfiel: Was meinst du zu folgender Überlegung?

    text=Text.Text
    avZeichenvorrat={"0-9","x","^","/","*","+","-","/",","}-Zahlen natürlich einzeln!

    For i=o to avZeichenvorrat.GetUpperBound(0)
    zeichen=avZeichenvorrat(i)
    text=Strings.Replace(text, zeichen,"",1,-1,....)

    If text="" then
    OK
    else
    MsgBox(text) 'mit Anzeige der Fehler

    Einfach Erlaubtes ausradieren. Wenn Rest bleibt, dann !!!,

    oder ist das zu naiv?

    ErfinderDesRades schrieb:

    Aber die Korrektheit des ganzen Strings kann Regex glaub nicht überprüfen.

    Wenn du auch Klammern hast, geht das mit Microsofts Regex-Implementierung im .NET Framework kaum - dafür bräuchte man Rekursive Patterns. Allerdings ist es für jeden anderen Term bestens geeignet ;)
    Leider hat Regex immer noch ein (mMn) großes Problem (zumindest bei .NET): Ein paar wünschenswerte Features wie Rekursion fehlen und die zurückgegebenen Werte sind nur schwer auszuwerten. Wären diese bspw. in einer Baumstruktur abrufbar, würde das vieles erleichtern. Diese Umstände gehören jedoch anscheinend zu Regex einfach dazu.
    Mir hat ein hoch-studierter mal erzählt, Regex sei eben eine Grammatik 2. Ordnung nach der Chomsky-Klassifikation, und das bringe mit sich, dass Regex nichts rekursives formulieren kann.
    Keine
    Ahnung, was das bedeutet, ich hab mir nur gemerkt, dass die
    Möglichkeiten bei aller Gewaltigkeit eben doch auch Grenzen haben.
    Und je näher man denen kommt, desto kryptischer werden auch die Ausdrücke.
    Und
    bei längeren Input-Texten geht dann auch die Performance in den Keller -
    hab ich mal deutlich gemerkt bei einem Xml-Syntax-Highlighter.
    Daher
    bau ich lieber kleinere, überschaubarere Regexe, die dann viele kleine
    Matches produzieren (etwa so Tokenizing), und höhere Struktur-Analysen
    mache ich mit der höheren Sprache VB.

    Und letztlich gibt es nie eine Validierung, die die parseabilität 100% sicher vorhersagen kann. Nur das Parsen selbst kann letztlich aussagen, obs klappt.
    Das
    habich festgestellt im Zusammenhang mit Serialisierung und mit
    typDatasets einlesen und sowas - da gibts ja auch Validier-Mechanismen,
    und ganz sicher sind die halt nie.
    Was mich ja zum CompactFormat geführt hat, bei dem ich ganz absichtlich jegliche Meta-Information weglasse.
    Hi,

    Wenn du auch Klammern hast, geht das mit Microsofts Regex-Implementierung im .NET Framework kaum - dafür bräuchte man Rekursive Patterns

    seitens Microsoft nicht, das stimmt. Dennoch, daran würd's theoretisch nich mal scheitern - zur Not schreibt man die RegEx-Abfrage in PHP und ruft sie im VB-Programm einfach ab (example.com/regexvalidator.php?mystring=whatever oder besser mit POST). Nachteil des Ganzen ist, dass eine Internetverbindung zwingend notwendig ist - will auch nich jeder.

    Würde auch gern mit RegEx rumexperimentieren, aber ich weiß nich mal was ein Polynom ist - und ich versuche es nach einem Blick in den Wikipedia-Artikel auch gar ned erst zu verstehen ;) Finde es sowieso Krass, wieviele Mathe-Gurus hier unterwegs sind, hab ich schon öfter bemerkt.

    Link :thumbup:
    Hello World