Oliver: replace mit Platzhalter

Ich habe ein kleines Problem mit replace und Platzhaltern. Ich will in einem String Platzhalter von a0 - a99 mit den Werten aus einem Array ersetzen.
Gedacht hatte ich mit das so:

for(x = 0; x <= 99; x++)
 {
 s = s.replace(/a' + x + '/gi, a[x]);
 }

Hab's auch schon mit /a + x + /gi probiert aber ohne Erfolg.

  1. Moin Moin!

    in einem String Platzhalter von a0 - a99 mit den Werten aus einem Array ersetzen.

    for(x = 0; x <= 99; x++)
    {
    s = s.replace(/a' + x + '/gi, a[x]);
    }

    Problem 1:

    Dein Code sucht in s den Ausdruck "a' + x + '", Du willst aber "a0" bis "a99" suchen.

    Lösungsansatz:

    RegExp-Objekt "von Hand" erzeugen: re=new RegExp("a"+i);

    Siehe SelfHTML -> Javascript -> Objekt-Referenz -> RegExp

    Problem 2:

    Deine Idee sucht erst nach a0, a1, .. a9. Ein "a10" wird schon als "a1" erkannt und ersetzt sein, wenn die Suche dort ankommt. Das gilt sinngemäß auch für a11 bis a99.

    Lösungsansätze:
    * Schleife rückwärts von 99 bis 0 laufen lassen
    * "a00" bis "a09" statt "a0" bis "a9" verwenden
    * Klammern: "a[2]", "a[20]" statt "a2", "a20"

    Problem 3:

    100 Schleifendurchläufe, die sich je nach Array-Werten auch noch verheddern können, weil sie die eingesetzten Werte auch nochmal bearbeiten.

    Lösungsansatz:

    RegExp-Objekt flexibler nutzen. Beginne mit dem Pattern /a(\d{1,2})/ (ungeklammert) oder /a[(\d{1,2})]/ (eckige Klammern), nutze die $1-Eigenschaft des RegExp-Objekts und nimm dessen numerischen Wert als Index für das Array. a[parseInt($1,10)] sollte diesen Part erledigen.

    Der einzige Haken bei diesem Ansatz ist, dass Replace wohl keinen Ausdruck als Ersatz akzeptiert, sondern nur einen String.

    In Perl würde man die ganze Aktion mit diesem Einzeiler erschlagen:

    $s=~s/a[(\d{1,2})]/$a[$i]/gie; # geklammert
    $s=~s/a(\d{1,2})/$a[$i]/gie; # ungeklammert

    Alexander

    1. Hi,

      nutze die $1-Eigenschaft des RegExp-Objekts und nimm dessen numerischen Wert als Index für das Array.

      Keine gute Idee: Das wird seit JavaScript 1.5 nicht mehr unterstützt.
      Es geht aber mit dem RegExp-Objekt:

        
      for(x = 0; x < a.length; x++){  
        s = s.replace( new RegExp("a"+x,"gi"), a[x] );  
      }  
      
      

      Don P

      1. Hi,

        nutze die $1-Eigenschaft des RegExp-Objekts

        Das wird seit JavaScript 1.5 nicht mehr unterstützt.

        Sagt wer? http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:RegExp jedenfalls nicht.

        Selbst wenn, kann man über den Rückgabewert von re.exec() auch noch auf diese Werte zugreifen. http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:RegExp:exec

        Es geht aber mit dem RegExp-Objekt:

        for(x = 0; x < a.length; x++){
          s = s.replace( new RegExp("a"+x,"gi"), a[x] );
        }

        
        >   
        > Don P  
          
        Das wird die Probleme 2 und 3 nicht lösen.  
          
        Alexander
        
        1. Sagt wer?

          Naja, vielleicht nicht ganz, aber es heißt hier u.A.: "Seit der JavaScript-Version 1.5 gilt das Auslesen der Treffer geklammerten Ausdrücke über RegExp.$1, RegExp.$2 und so weiter als veraltet."

          Das wird die Probleme 2 und 3 nicht lösen.

          Wieso nicht? Es macht genau das was gefordert war: Es durchläuft das Array a mit den Ersetzungswerten und ersetzt im String s alle Vorkommen von a+Arrayindex (also a0 bis a99, wenn a entsprechend lang ist) durch den entsprechenden Ersetzungswert. Probier's doch aus:

            
          var a = ['a','b','c','d','e'];  
          var s = "-a0-a1-a2-a3-a4-a2-";  
          for(x = 0; x < a.length; x++){  
            s = s.replace( new RegExp("a"+x,"g"), a[x] );  
          }  
          
          
          1. Sagt wer?

            Naja, vielleicht nicht ganz, aber es heißt hier u.A.: "Seit der JavaScript-Version 1.5 gilt das Auslesen der Treffer geklammerten Ausdrücke über RegExp.$1, RegExp.$2 und so weiter als veraltet."

            Das ist aber etwas deutlich anderes als "nicht mehr unterstützt". Es wird definitiv noch unterstützt, man sollte es aber vielleicht nicht mehr verwenden.

            Das wird die Probleme 2 und 3 nicht lösen.

            Wieso nicht? Es macht genau das was gefordert war: Es durchläuft das Array a mit den Ersetzungswerten und ersetzt im String s alle Vorkommen von a+Arrayindex (also a0 bis a99, wenn a entsprechend lang ist) durch den entsprechenden Ersetzungswert.

            Das tut es nicht.
            (1) Gefordert war a0 bis a99, nicht a0 bis a+Arraylänge
            (2) Was passiert bei s="a10"? Erst nachdenken, dann posten! Oder weiterlesen:

            s.replace(/a1/gi,a[1]) schägt zu und ersetzt die ersten zwei Zeichen von s durch den Wert von a[1].

            s.replace(/a10/gi,a[10]) wird erst danach ausgeführt und findet in s kein "a10" mehr, es sei denn, der Wert von a[1] ist zufällig "a1", "a10", "a10foobar" oder "a10 Mir doch egal!". Ist a[1] aber z.B. "foobar", ist s nach dem replace(/a1/gi,a[1]) "foobar0". Und richtig übel wird es, wenn a[1] den String "a10" enthält, z.B. den Wert "ich mag a10 nicht" hat. Dann wird nämlich in der Ersetzung noch mal ersetzt. Bei a[10]="Unsinn" und s="a10" entsteht also nicht "Unsinn", sondern "ich mag Unsinn nicht".

            Problem 1 nicht wie spezifiziert gelöst, Problem 2 nicht gelöst, Problem 3 nicht gelöst.

            Alexander

            1. (1) Gefordert war a0 bis a99, nicht a0 bis a+Arraylänge

              Das ist doch Haarspalterei, sorry. Meine Lösung ist da sogar eine Verbesserung, weil sie allgemeiner ist, als genau bis 99. Außerdem muss man nur die Schleifenbedingung entsprechend ändern, wenn wirklich genau bis 99 gehen will. Was dann aber, wenn das Array mal kürzer ist? Genau, ein Laufzeitfehler...

              (2) Was passiert bei s="a10"? Erst nachdenken, dann posten! Oder weiterlesen

              Jaja schon gut, hatte dir ja schon teilweise recht gegeben, was dein Problem 2 betrifft, aber das wird, wie du richtig geschrieben hast, einfach durch Rückwärtslaufen erledigt.

              Dein Problem 3 sehe ich gar nicht. Jedenfalls nicht in der Aufgabenstellung, wenn du schon haarspalerisch argumentiert. Es steht nämlich nirgends, dass die Erstzungswerte etwas wie "ich mag a10 nicht" sein können, oder dass sie überhaupt so aufgebaut sein dürfen, dass wieder neue ann entstehen. Das würde ja auch wirklich wenig Sinn machen, oder aber es wäre absichtlich eine ganz raffinierte Sache. Die Aufgabenstellung sagt darüber jedenfalls nichts.

              Don P

              1. Das ist doch Haarspalterei, sorry.

                Natürlich ist das Haarspalterei. Es muß Haarspalterei sein, weil Computer so blöd sind, exakt das zu machen, was man ihnen sagt, und nicht das, was man meint. Deswegen muß das Problem präzise beschrieben werden.

                Meine Lösung ist da sogar eine Verbesserung, weil sie allgemeiner ist, als genau bis 99.

                Es ist besser, wenn es die gestellte Aufgabe nicht erfüllt?

                "a100" soll laut Aufgabenstellung zu a[10]+"0" evaluiert werden, und nicht zu a[100]. Dein Lösungsansatz ist ab Array-Längen von 101 defekt.

                Außerdem muss man nur die Schleifenbedingung entsprechend ändern, wenn wirklich genau bis 99 gehen will. Was dann aber, wenn das Array mal kürzer ist? Genau, ein Laufzeitfehler...

                Nein. Ein Laufzeitfehler entsteht vielleicht in Java, aber definitiv NICHT in Javascript. Ein nicht vorhandenes Array-Element evaluiert zu einem undefinierten Wert. Bei einem String-Concat wird daraus der String "undefined". Das ist vielleicht nicht hübsch, und vielleicht auch nicht ganz das, was Oliver sich gedacht hat. Aber es gibt keinen Laufzeitfehler.

                Jaja schon gut, hatte dir ja schon teilweise recht gegeben, was dein Problem 2 betrifft, aber das wird, wie du richtig geschrieben hast, einfach durch Rückwärtslaufen erledigt.

                Beachte das Wörtchen "Lösungsansatz". Das Rückwärtslaufen löst nur das Problem 2, nicht das Problem 3. Im Gegenteil, es macht Problem 3 schlimmer, weil die letzten 10 Durchläufe schon auf "a" + eine Ziffer anspringen.

                Dein Problem 3 sehe ich gar nicht. Jedenfalls nicht in der Aufgabenstellung, wenn du schon haarspalerisch argumentiert. Es steht nämlich nirgends, dass die Erstzungswerte etwas wie "ich mag a10 nicht" sein können, oder dass sie überhaupt so aufgebaut sein dürfen, dass wieder neue ann entstehen. Das würde ja auch wirklich wenig Sinn machen, oder aber es wäre absichtlich eine ganz raffinierte Sache. Die Aufgabenstellung sagt darüber jedenfalls nichts.

                Richtig. Die Aufgabenstellung sagt darüber gar nichts. Sie schließt keine Werte für die Array-Elemente aus. Auch nicht solche, die ein "a" gefolgt von ein oder zwei Ziffern enthalten. Deswegen sollte man besser davon ausgehen, dass solche Werte vorkommen können und nicht erneut ersetzt werden sollen. Oder noch besser: Man fragt nach, wie sich der Algorithmus in diesem Fall verhalten soll und bessert die Aufgabenstellung / Spezifikation nach.

                Alexander

                1. Donnerwetter,

                  Es muß Haarspalterei sein, weil Computer so blöd sind, exakt das zu machen, was man ihnen sagt, und nicht das, was man meint.

                  Verstehe, Computer sind also genau wie du...

                  Meine Lösung ist da sogar eine Verbesserung, weil sie allgemeiner ist, als genau bis 99.

                  Es ist besser, wenn es die gestellte Aufgabe nicht erfüllt?

                  Weia, bekomme ich jetzt eine 6? Wie soll ich da noch ruhig schlafen?
                  Aber es ist zum Glück tatsächlich besser, gibt sogar ne 1+, wegen aussergewöhnlicher Leistung.

                  "a100" soll laut Aufgabenstellung zu a[10]+"0" evaluiert werden, und nicht zu a[100]. Dein Lösungsansatz ist ab Array-Längen von 101 defekt.

                  Es geht um a0 bis a99. Ein a100 ist gar nicht geplant, und falls doch, arbeitet meine Routine damit sicher besser im Sinn von Oliver als ein a[10]+"0". Das weiss ich, weil ich im Unterschied zu blöden Computern sogar verstehe, was gemeint ist, und nicht nur, was dasteht.

                  Ein nicht vorhandenes Array-Element evaluiert zu einem undefinierten Wert. Bei einem String-Concat wird daraus der String "undefined". Das ist vielleicht nicht hübsch, und vielleicht auch nicht ganz das, was Oliver sich gedacht hat.

                  *Vielleicht* nicht? Mit Sicherheit nicht!

                  Aber es gibt keinen Laufzeitfehler.

                  Na Super. Du hast recht und ich meine Ruhe.

                  Das Rückwärtslaufen löst nur das Problem 2

                  Habe ich denn etwas anderes behauptet?

                  Im Gegenteil, es macht Problem 3 schlimmer [...]

                  Ein Problem 3 sehe ich noch immer nicht. Wiederum deshalb, weil ich im Unterschied zu blöden Computern sogar verstehe, was gemeint ist, und nicht nur, was dasteht. Sollte so ein Problem überhaupt auftreten können, dann würde man das vernünftigerweise im Vorfeld lösen, und das ganze Konzept überarbeiten, sicher nicht erst bei der Ersetzungsroutine.

                  P.S.: Eigentlich wollte ich mich erst nicht weiter dazu äussern. Aber du scheinst so eine Genugtuung an der Rachthaberei zu haben, dass ich es mir nicht verkneifen konnte, nochmal zu kontern :) Kannst jetzt ruhig noch einmal das letzte Wort haben, ich sag nichts mehr dazu.

                  Gruß, Don P

          2. Da ich immer noch nicht ganz weiter komme mal etwas mehr ausholen:
            Das ganze stellt Messwerte in einer Art Tabelle dar, für jeden Sensor gibt es eine Zeile A...B...C... (im Moment nur A) und Messwerte 0...99. Die ganze HTML-Datei wird von einem Perl-Skript erzeugt und enthält alle Formeln und Werte.
            Im Script ist eine Formel hinterlegt die über Buttons beeinflusst werden kann.
            Durch die Buttons werden Platzhalter in der Formel beinflusst und danach kann über einen Button die Berechnung aktiviert werden und das Resultat als alert angezeigt werden.
            Der Ablauf wäre (bei mehreren Sensoren):

            pos = 0;
            for(a = 0; a < sensoren; a++)
             {
             buchstabe = String.fromCharCode(a + 65);
             formeltmp = formel;
             for(b = messwert; b >= messwert; b--)
              {
              formeltmp = formeltmp.replace(/...../gi, a[pos]);

            }
             anzeige();
             pos++;
             }

            Bei .... sollten dann Platzhalter A2, A1 etc. durch pos bezeichnete Werte aus dem Array ersetzt werden. Hoffe es ist einigermassen verständlich....

            1. Da ich immer noch nicht ganz weiter komme mal etwas mehr ausholen:
              Das ganze stellt Messwerte in einer Art Tabelle dar, für jeden Sensor gibt es eine Zeile A...B...C... (im Moment nur A) und Messwerte 0...99. Die ganze HTML-Datei wird von einem Perl-Skript erzeugt und enthält alle Formeln und Werte.
              Im Script ist eine Formel hinterlegt die über Buttons beeinflusst werden kann.
              Durch die Buttons werden Platzhalter in der Formel beinflusst und danach kann über einen Button die Berechnung aktiviert werden und das Resultat als alert angezeigt werden.
              Der Ablauf wäre (bei mehreren Sensoren):

              pos = 0;
              for(a = 0; a < sensoren; a++)
              {
              buchstabe = String.fromCharCode(a + 65);
              formeltmp = formel;
              for(b = messwert; b >= messwert; b--)
                {
                formeltmp = formeltmp.replace(/...../gi, a[pos]);

              }
              anzeige();
              pos++;
              }

              Deine äußere Laufvariable und Deine Daten haben den gleichen Namen. So kann das nicht funktionieren. Warum rufst Du anzeige() für jede Spalte auf? Warum rufst Du anzeige() ohne jegliche Parameter auf? Die innere Schleife läuft wesentlich länger und anders, als Du beabsichtigst.

              Bitte poste das komplette generierte HTML und keine Pseudoscripte. Und vielleicht postest Du auch mal die Formel und ihre "Beeinflussung".

              Bei .... sollten dann Platzhalter A2, A1 etc. durch pos bezeichnete Werte aus dem Array ersetzt werden. Hoffe es ist einigermassen verständlich....

              Ansatzweise. Warum machst Du das in Javascript, wenn Du ohnehin schon mit Perl arbeitest? Die für Perl nötigen REs habe ich schon gepostet. Pack die Formel ins Perl und mache die "Beeinflussung" der Formel durch CGI-Parameter.

              Alexander

              1. pos = 0;
                for(a = 0; a < sensoren; a++)
                {
                buchstabe = String.fromCharCode(a + 65);
                formeltmp = formel;
                for(b = messwert; b >= messwert; b--)
                  {
                  formeltmp = formeltmp.replace(/...../gi, a[pos]);

                }
                anzeige();
                pos++;
                }

                Die innere Schleife läuft wesentlich länger und anders, als Du beabsichtigst.

                D'oh! Die innere Schleife läuft exakt einmal ...

                Alexander

              2. Das Perl-Script welches die HTML-Datei erzeugt läuft nicht auf einem PC sondern einem Messsystem mit beschränktem RAM und ohne Möglichkeit für einen Webserver. Das System versendet jeden Tag eine solche Datei per sendmail an einen Techniker. Die Formel kann ich nicht posten da diese nicht öffentlich ist. Bei dem Messsystem handelt es sich um ein Gerät an welches bis zu 20 Sensoren angeschlossen werden können und dieses in bestimmbaren Zeitabständen Messungen durchführt. Die versendete HTML-Datei ist eine standalone Lösung. In einer Tabelle (eine Zeile pro Sensor - im Moment nur einer) wird jeder 10. Messwert angezeigt. Durch Buttons können nun verschiedene Werte errechnet und angezeigt werden in welche auch vom Medium abhängige Werte einfliessen. Ich habe also ein Array a welches von 0-99 die Werte des ersten Sensors enthält und von 100-198 die des zweiten etc.
                In den Formeln soll diese Werte dann eingesetzt werden, also A1 = a[0], A12 = a[11]...später dann B1 = a[100] und so weiter. In der Formel könnte man auch z.B.
                [A12] anstatt A12 einsetzen.....
                Ist schon ein etwas schwieriges Problem.

                1. Ist schon ein etwas schwieriges Problem.

                  Naja, wenn du einfach zeigen würdest was du mit was ersetzen willst, wäre es ein einfaches.

                  Struppi.

                2. Hallo Oliver,

                  Ich habe also ein Array a welches von 0-99 die Werte des ersten Sensors enthält und von 100-198 die des zweiten etc.

                  1. Bei bis zu 20 Sensoren ergibt das eine max. Länge des Arrays von 100 Messwerten * 20 Sensoren = 2000 Arrayelemente. Es müssen aber nicht immer alle 2000 Elemente tatsächlich im Array existieren.
                  Ist das so richtig?

                  In den Formeln soll diese Werte dann eingesetzt werden, also A1 = a[0], A12 = a[11]...später dann B1 = a[100] und so weiter.

                  2. Die "Formeln" sind normale Strings, die Paltzhalter namens A1, A2 usw. bis A2000 enthalten können. Es sind immer alle 2000 Platzhalter vorhanden. Es müssen nicht immer alle 2000 Platzhalter gleichzeitig ersetzt werden, sondern blockweise zuerst 100 Stück, nachträglich dann zusätzlich zu den bereits ersetzten die nächsten 100 Stück usw.
                  Ist das so richtig?

                  »»In der Formel könnte man auch z.B. [A12] anstatt A12 einsetzen.....

                  3. A12 wird ja nicht eingesetzt, sondern an Stelle von "A12" wird der Wert des Array-Elements a[11] eingesetzt. Die Formel kann aber vor der Ersetzung so aufbereitet werden, dass alle Platzhalter A1...A2000 von Begrenzungszeichen umgeben sind, so dass sie vor dem Einsetzen der Messwerte z.B. als {A1}...{A2000} in der Formal stehen.
                  Ist das so richtig?

                  Ist schon ein etwas schwieriges Problem.

                  Nicht, wenn man es genau beschreibt...

                  Don P

                  1. Ja die Beschreibung ist recht zutreffend, die Formeln enthalten aber selten mehr als 20 Platzhalter gleichzeitig vorhanden.

        2. Das wird die Probleme 2 und 3 nicht lösen.

          Ach so, jetzt seh' ich's auch: Dein Problem 2 muss durch Rückwärtslaufen erledigt werden, hast recht.

          Problem 3 tritt vielleicht gar nicht auf. Am besten wär's, wenn die Suchstrings Delimiter hätten, die man mit abfragen könnte.

          Don P

    2. Also ich habs immer noch nicht ganz kapiert....

      1. Also ich habs immer noch nicht ganz kapiert....

        Was soll ich da machen? Mein Telepathie-Gen ist leider familiär bedingt defekt. Dir wird also nichts übrig bleiben, als mir Dein Problem auf die traditionelle Art und Weise bewußt zu machen.

        Alexander

  2. Hello out there!

    s = s.replace(/a' + x + '/gi, a[x]);

    So nicht.

    Variablen in RegExp

    See ya up the road,
    Gunnar

    --
    „Und [dieses Forum] soll […] auch ein Fachforum bleiben und kein Psychologieforum werden.“ (Kirsten Evers)