Searcher: RegExp-Späßchen(?)

problematische Seite

Zunächst mal: da steht geschrieben „Beachten Sie: Vor der JavaScript-Version gab es noch …“. (🤪 gibt es irgendwo ein JavaScript ohne Version?)

Und dann zum Späßchen: ich verwende (beispielsweise) ein RegExp = /(?<val_>(?<msd_>\d{1,3}(?:\.?\d{3})*?)(,(?<lsd_>\d{0,2}))?)/;. Wenn ich dann aber nach manchem Ergebnis suche, gibt es ein nicht gerade erwartetes undefined:

links: Quelltext; rechts: „Ergebnis“ in der Konsole

Meine Vermutung: wenn in .groups das erste Element undefined ist, dann meint die sonst eigentlich immer funktionierende Nachfrage nach den offensichtlich sehr wohl gefundenen (anderen) Elementen, die gäbe es ja garnicht. Nur wenn man explizit nach .groups.…fragt, setzt die Erinnerung dann wieder ein.

Jedenfalls: benannte Gruppen „möchten manchmal anonym sein“ …

  1. problematische Seite

    Hi,

    Zunächst mal: da steht geschrieben „Beachten Sie: Vor der JavaScript-Version gab es noch …“. (🤪 gibt es irgendwo ein JavaScript ohne Version?)

    Und dann zum Späßchen: ich verwende (beispielsweise) ein RegExp = /(?<val_>(?<msd_>\d{1,3}(?:\.?\d{3})*?)(,(?<lsd_>\d{0,2}))?)/;. Wenn ich dann aber nach manchem Ergebnis suche, gibt es ein nicht gerade erwartetes undefined:

    ich würde benannte und anonyme Gruppe (anonym ist die, die mit (, anfängt) nicht mischen. Wenn der Inhalt der Gruppe nicht gebraucht wird, dann (?:, wenn's doch gebraucht wird, dann auch einen Namen vergeben.

    links: Quelltext; rechts: „Ergebnis“ in der Konsole

    Meine Vermutung: ca. 17 Pixel im Code-Bild haben die falsche Farbe.

    (Nein, ich werde das jetzt nicht abtippen, um's zu überprüfen)

    cu,
    Andreas a/k/a MudGuard

    1. problematische Seite

      Ungefähr 17 Pixel? Was das wohl sein könnte? Eventuell ein „_“, der da als Überbleibsel manches Versuchs rund ums Problem dahinvegetierte? Der war, vorerst, ohne Bedeutung und ist jetzt auch weg.

      Ansonsten: es handelt sich ja nicht um „meine“ Farben. Die stammen „links“ vom Editor und „rechts“ von des Browsers Entwicklungsumgebung. Insofern ist „falsch“ … verwirrend.

  2. problematische Seite

    Hallo Searcher,

    Zunächst mal: da steht geschrieben „Beachten Sie: Vor der JavaScript-Version gab es noch...

    Früher stand da mal "Vor der JavaScript-Version 1.5 gab es noch..." - also ECMAScript 3. Ich habe jetzt wenig Lust auf intensivere forensische Analysen, aber die AI meines geringsten Misstrauens sagt, das seien alte Netscape-Features, die vom IE und allen neueren Browsern übernommen wurden. Aktuelle Chromia kennen diese statischen Properties noch, und es gibt wohl tatsächlich ein Projekt bei TC39[1], sie als Legacy-Features neu zu standardisieren.


    Von

    RegExp = /(?<val_>(?<msd_>\d{1,3}(?:\.?\d{3})*?)(,(?<lsd_>\d{0,2}))?)/
    

    rate ich übrigens dringend ab, das kann schwere Verwirrung auslösen. Wenn es wie im Screenshot ein initialisiertes static Property ist, killst Du immerhin die Konstruktorfunktion von RegExp nicht, aber ich würde die Namen bekannter globaler Funktionen nicht für eigene Properties verwenden.

    Warum deine RegExp merkwürdige Dinge tut, liegt daran, dass Dein Muster keinen Ende-Delimiter für die Zahl enthält. Beachte, dass match[0] den Wert "123" hat, d.h. mehr hat er für dieses Match nicht verwendet. Du hast die .\d{3} Gruppe als nicht-gierige Wiederholung definiert, das bedeutet: er matcht sie so WENIG wie möglich. Die Dezimalgruppe ist optional, und die hast er auch ungierig übersprungen (was mich etwas wundert), und daraufhin hat er noch den Punkt übersprungen und den Rest für den zweiten Match aufbewahrt.

    Mit einem Regex-Tester wie https://regex101.com/ sieht man, dass Du in Wahrheit zwei Matches hast. Den zweiten Match bekommst Du von exec aber nicht, du musst dafür ein g als Option an die Regex anhängen, und exec so lange aufrufen, bis null zurückkommt.

    Forenzitat 1225 weiß seit 2008 von diesem Problem, und meine Meinung dazu wurde 2016 zu Forenzitat 2121

    Was sich als Delimiter eignet, hängt von deinen Strings ab. Welche Eingaben erwartest Du, was willst Du akzeptieren, was nicht?

    Warum brauchst Du den Teil vor dem ersten Tausendertrenner und die Nachkommastellen separat?

    Warum zwingst Du den Anwender, Tausenderkommas zu setzen und korrekte Gruppierungen einzugeben?

    Regexe, die Plausibilitäten mit prüfen sollen, muss man ankern (also ^ davor und $ dahinter), ansonsten prüfen sie nur den Teil, der plausibel ist.

    Meine Empfehlung: Zuerst trimmen, dann alle Punkte rausschmeißen, dann EVENTUELL die Syntax prüfen (/^\d{1,}(,\d{0,2})?$/? - mehr nicht, ggf. maximale Stellenzahl vor dem Komma hinzufügen), und dann ganz stumpf parseFloat(input.replace(",", ".")) aufrufen.

    Es sei denn, du willst gar nicht den Zahlenwert haben, sondern irgendwas anderes tun…

    Rolf

    --
    sumpsi - posui - obstruxi

    1. https://github.com/tc39/proposal-regexp-legacy-features ↩︎

    1. problematische Seite

      1. an der „Leiche“, dem „_“ links in static test(string) kann man noch sehen, daß ich da schon einige Experimente unternommen hatte, um an mein “missing link” doch noch heranzukommen. Da war mir gerade recht, was „irgendwie funktioniert“ hat. Aber natürlich stimmt der Einwand, denn auch so weiß man schnell (selbst) nicht, was für ein Ding man da gerade ansieht. (Sprich: das wurde geändert.)

      Und das Konstrukt? Nun, zumindest tut ein "^(?P<i>[^\d]?)(?<val_>(?P<msd_>\d{1,3}(?:.?\d{3})?)(,(?P<lsd_>\d{0,2}))?)(?P<r>[^\d]*)$" in Bbedit brav das, was ich mir gedacht hatte — die Aufrufe im Skript bekommen immer nur eine ganze „Zeile“, so daß ich da nicht auf Anfang/Ende getestet habe.

      Und nein, ich zwinge keine Anwender, ich werde gezwungen: das Skript soll mir irgendwann mal die Inhalte von gegebenen Tabellen einer Webseite in sinnvolle Inhalte wandeln. Da findet man es nämlich angebracht, beispielsweise anstelle einer „0“ (für eine Anzahl) auch mal ein „-“ oder „ungesetzt“ auszuliefern. Auch sonst ist die Zahlendarstellung da eher mit Vorsicht zu genießen, so daß ich meinen „Zahlendetektor“ dafür möglichst „störungsunempfindlich“ bauen möchte.

      Dabei bin ich dann eben über dieses „mal klappt es, mal nicht“ gestolpert und war doch „etwas überrascht“, als ich mit console.table solche wie die gezeigte fand: da sind die Gruppen anscheinend genau da, wo ich sie erwartet habe. Und trotzdem werden „meine Nachkommastellen“ im Skript nicht gefunden.

      Daß ich in solchen Fällen dann aber mit .groups.val_ doch fündig wurde … paßt auch wieder nicht zu einem „das sind zwei Ausdrücke“.

      BTW: das „Gezappel mit den Unterstrichen“ (ich habe gerade noch so einen Vagabunden gefunden) stammt übrigens daher, daß ich versucht habe, „Fipptehler“ auszumerzen: wie schnell hat man einem Objekt ein ganz neues Element (mit einem Buchstaben mehr oder weniger oder einem falschen mittendrin im Namen) eingepflanzt?

      Also habe ich es mit “computed properties” versucht. Damit sich „meine“ Speicher-Strukturen doch mehr so verhalten, wie vlt. ein C-struct oder ein Pascal record: meckern bei „Fiptelher“ ist da ja fest eingebaut.

      Aber das ist dann doch nur eine Katze (und kein Hund) geworden, die sich in den eigenen Schwanz beißt: wenn man da „den Kreis schließen“ möchte, bräuchte man plötzlich den Bezeichner, in dem die Property-Namen abgelegt wurden, als Namen für den Zugriff …

      Das Ergebnis da: es ist wieder raus …

  3. problematische Seite

    Hallo Searcher,

    Meine Vermutung: (...)

    ist leider haltlos. Da findet keine lazy-Initialisierung statt. Wie gesagt: Du hattest 2 Matches, weil Du non-greedy (*?) bestellt und eine Abmagerungskur bekommen hast 😉

    Rolf

    --
    sumpsi - posui - obstruxi
    1. problematische Seite

      Neben einigen anderen Dingen (z.B. die oben erwähten „vagabundierenden _“) ist auch das greedy/non-greedy ein Teil aus dem „Versuchslabor“. Auch /(?<val_>(?<msd_>\d{1,3}(?:\.?\d{3})*?)(?:,(?<lsd_>\d{0,2}))?)/ (non-capturing group!) war da ursprünglich drin. Was aber kein anders Verhalten gezeigt hat.

      Die diversen Unternehmungen sollten nur den Browser (seine JS-Maschine) zur Herausgabe von Reaktionen provozieren.

      Im Augenblick habe ich jetzt eine anscheinend funktionierende Formulierung zustande gebracht. Im Augenblick. — Mal sehen, wann mir wieder ein throw aus den Klassen-Interna um die Ohren fliegt …