BSF: RegExp

Hallo zusammen,

ich möchte in einem String alle mit '' umschlossenen Werte finden und diese wiederum mit etwas anderem umschliessen.

Also z.B. hieraus --> "select xyz from table1 where col1 like 'a%' and col2 like 'b%'"

soll folgendes werden --> "select xyz from table1 where col1 like LOWER('a%')
and col2 like LOWER('b%')"

Ich habe mir dazu die Funktion RegExp einmal angesehen, werde aber noch nicht so richtig schlau draus.

Für Tips wäre ich sehr dankbar,

Gruss,

  1. Naja, ein Problem sehe ich trotzdem:

    Das Script muss ja erkennen ob eine Klammer geöffnet werden soll, oder geschlossen. Nach deinem Beispiel kannst du "replace" benutzen, mit einer variable die sich merkt ob eine Klammer auf -oder zu geht.

  2. gruss BSF,

    /*  
      
      gesucht werden sollen also _alle_ durch einfache bzw. durch doppelte  
      hochkommata eingefassten zeichensequenzen:  
      
    1)  
      ['"] - *matched* genau ein zeichen, welches entweder ein einfaches  
      oder ein doppeltes hochkomma ist.  
    2)  
      [^'"]* - *matched* genau keins, eins oder mehrere zeichen, die weder  
      einfache noch doppelte hochkommata sind.  
    3)  
      (['"]) - wie (1), nur das dieses zeichen auf einem internen ueber  
      »1« zu adressierenden *speicher* abgelegt wird.  
    4)  
      [^\\1]* - wie (2), nur das hier schon mit der internen gerade unter  
      (3) genannten referenz auf deas erste *gematchte* zeichen gearbeitet  
      wird.  
    5)  
      ([^\\1]*) wie (4), nur das der ganze kram jetzt ebenfalls gespeichert  
      wird - diesmal unter der internen referenz »2«.  
    6)  
      \1 wie unter (1), nur das hier ebenfalls wieder mit der internen  
      referenz, wie auch gerade unter (4) beschrieben, gearbeitet wird.  
      
      
      arbeitsprobe - bitte *copy and paste* unter [link:http://jconsole.com@title=jconsole.com]:  
    */  
      
      
    var str, regX;  
      
    str = "select xyz from table1 where col1 like 'a%' and col2 like \"b%\"";  
    regX = (/(['"])([^\\1]*)\1/g);  
      
    print(regX.test(str));  
    print(str.replace(regX, "LOWER($1$2$1)"));  
      
      
    str = "select xyz from table1 where col1 like \"c%\" and col2 like 'd%'";  
    regX = (/(['"])([^\\1]*)\1/g);  
      
    print(regX.test(str));  
    print(str.replace(regX, (function () {  
      return ("LOWER(" + arguments[1] + arguments[2] + arguments[1] + ")");  
    })));
    

    so long - peterS. - pseliger@gmx.net

    --
    »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
    Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
    ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
    1. Hallo Peter,

      das ist schon mal ganz dicht dran!
      Allerdings habe ich in meinem String ausschließlich einzelne Hochkommata,
      wenn ich also das hier --> str = "select xyz from table1 where col1 like "c%" and col2 like 'd%'";
      in das hier --> str = "select xyz from table1 where col1 like 'c%' and col2 like 'd%'"; ändere, bekomme ich das -->
      select xyz from table1 where col1 like LOWER('c%' and col2 like 'd%')
      Hast Du da noch einmal einen Tip?

      Vielen Dank schonmal für die Mühe, die Du Dir gemacht hast!

      Gruss,

      BSF

      gruss BSF,

      /*

      gesucht werden sollen also alle durch einfache bzw. durch doppelte
        hochkommata eingefassten zeichensequenzen:

      ['"] - matched genau ein zeichen, welches entweder ein einfaches
        oder ein doppeltes hochkomma ist.
      2)
        [^'"]* - matched genau keins, eins oder mehrere zeichen, die weder
        einfache noch doppelte hochkommata sind.
      3)
        (['"]) - wie (1), nur das dieses zeichen auf einem internen ueber
        »1« zu adressierenden speicher abgelegt wird.
      4)
        [^\1]* - wie (2), nur das hier schon mit der internen gerade unter
        (3) genannten referenz auf deas erste gematchte zeichen gearbeitet
        wird.
      5)
        ([^\1]*) wie (4), nur das der ganze kram jetzt ebenfalls gespeichert
        wird - diesmal unter der internen referenz »2«.
      6)
        \1 wie unter (1), nur das hier ebenfalls wieder mit der internen
        referenz, wie auch gerade unter (4) beschrieben, gearbeitet wird.

      arbeitsprobe - bitte copy and paste unter [link:http://jconsole.com@title=jconsole.com]:
      */

      var str, regX;

      str = "select xyz from table1 where col1 like 'a%' and col2 like "b%"";
      regX = (/(['"])([^\1]*)\1/g);

      print(regX.test(str));
      print(str.replace(regX, "LOWER($1$2$1)"));

      str = "select xyz from table1 where col1 like "c%" and col2 like 'd%'";
      regX = (/(['"])([^\1]*)\1/g);

      print(regX.test(str));
      print(str.replace(regX, (function () {
        return ("LOWER(" + arguments[1] + arguments[2] + arguments[1] + ")");
      })));

      
      >   
      >   
      > so long - peterS. - pseliger@gmx.net  
      >   
      > 
      
      1. hallo again BSF,

        Allerdings habe ich in meinem String ausschließlich einzelne Hochkommata,
        wenn ich also das hier --> str = "select xyz from table1 where col1 like "c%" and col2 like 'd%'";
        in das hier --> str = "select xyz from table1 where col1 like 'c%' and col2 like 'd%'"; ändere, bekomme ich das -->
        select xyz from table1 where col1 like LOWER('c%' and col2 like 'd%')

        ups ... warum? ... das darf eigentlich ueberhaupt nicht sein. aber ein test
        legt tatsaechlich nahe, dass die RegExp-engine dort wirklich »gierig« suchend
        zu werke geht, alles zwischen dem ersten und dem letzten vorkommen des zuerst
        *gematchten* zeichens mitnimmt, und dabei das ausdruecklich nicht gierig
        formulierte muster einfach ignoriert (C&P >> jconsole.com):

        var str, regX = (/(['"])([^\\1]*)\1/g);  
          
        str = "select xyz from table1 where col1 like 'a%' and col2 like 'b%' and col3 like \"xy%\" and col4 like 'ik%'";  
        print(regX.test(str));  
        print(str.replace(regX, (function () {  
          alert("arguments[0] : " + arguments[0] + "\narguments[1] : " + arguments[1] + "\narguments[2] : " + arguments[2]);  
          return ("LOWER(" + arguments[1] + arguments[2] + arguments[1] + ")");  
        })));  
          
        str = "select xyz from table1 where col1 like \"c%\" and col2 like \"d%\" and col3 like 'ab%' and col4 like \"cd%\"";  
        print(regX.test(str));  
        print(str.replace(regX, (function () {  
          alert("arguments[0] : " + arguments[0] + "\narguments[1] : " + arguments[1] + "\narguments[2] : " + arguments[2]);  
          return ("LOWER(" + arguments[1] + arguments[2] + arguments[1] + ")");  
        })));
        

        Hast Du da noch einmal einen Tip?

        fuehrt man das muster aber mal auf jeweils ein bestimmtes hochkomma zurueck,
        und ist damit nicht mehr auf die »backreference« angewiesen, laufen die jeweils
        zugeordneten testcases anstandlos durch (C&P >> jconsole.com):

        var str, regX;  
          
        str = "select xyz from table1 where col1 like 'a%' and col2 like 'b%' and col3 like \"xy%\" and col4 like 'ik%'";/*  
        regX = (/(['"])([^\\1]*)\1/g);*/  
        regX = (/(')([^']*)'/g);  
          
        print(regX.test(str));  
        print(str.replace(regX, "LOWER($1$2$1)"));  
          
        str = "select xyz from table1 where col1 like \"c%\" and col2 like \"d%\" and col3 like 'ab%' and col4 like \"cd%\"";/*  
        regX = (/(['"])([^\\1]*)\1/g);*/  
        regX = (/(")([^"]*)"/g);  
          
        print(regX.test(str));  
        print(str.replace(regX, (function () {  
          alert("arguments[0] : " + arguments[0] + "\narguments[1] : " + arguments[1] + "\narguments[2] : " + arguments[2]);  
          return ("LOWER(" + arguments[1] + arguments[2] + arguments[1] + ")");  
        })));
        

        schoen - damit waere Dein problem geloest. die generische loesung, die das
        gemischt auftretende vorkommen beide arten hochkommata unterstuetzt, bliebe
        aber weiter fehlerhaft ...
        (test, test ,test ...) ...
        ...
        ich weiss zwar immer noch nicht, warum die RegExp-implementationen aller
        getesteten browser so einig in der gierigen interpretation des mit der
        »backreference« arbeitenden ausdrucks waren - zumindest sind sie sich auch
        bei folgendem test einig, der das problem zwar loest, indem das muster
        nocheinmal ausdruecklich als *nicht gierig* gekennzeichnet wird, mich aber
        trotzdem noch fragend zuruecklaesst (C&P >> jconsole.com):

        var str;/*  
        var regX = (/(['"])([^\\1]*)\1/g);*/  
        var regX = (/(['"])([^\\1]*?)\1/g);  
          
        str = "select xyz from table1 where col1 like 'a%' and col2 like 'b%' and col3 like \"xy%\" and col4 like 'ik%'";  
        print(regX.test(str));  
        print(str.replace(regX, "LOWER($1$2$1)"));  
          
        str = "select xyz from table1 where col1 like \"c%\" and col2 like \"d%\" and col3 like 'ab%' and col4 like \"cd%\"";  
        print(regX.test(str));  
        print(str.replace(regX, (function () {  
          alert("arguments[0] : " + arguments[0] + "\narguments[1] : " + arguments[1] + "\narguments[2] : " + arguments[2]);  
          return ("LOWER(" + arguments[1] + arguments[2] + arguments[1] + ")");  
        })));
        

        so long - peterS. - pseliger@gmx.net

        --
        »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
        Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
        ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
        1. Hi,

          und dabei das ausdruecklich nicht gierig
          formulierte muster

          Wo hast Du etwas von nicht-gierig gesagt?

          regX = (/(['"])([^\1]*)\1/g);

          Das sucht nach einem ' oder ", gefolgt von beliebig vielen (gierig!) Zeichen, solange es sich nicht um einen Backslash oder eine 1 handelt, gefolgt von dem ' oder " (so wie es am Anfang gefunden wurde).

          Nicht-gierig wäre es, wenn nach dem Stern noch ein ? stünde.

          Back-References funktionieren m.W. nicht in Zeichenklassen.

          Da es für das Umschließen mit LOWER() wurscht ist, ob die '' im Match dabei sind und dann im replacement nicht mehr gesetzt werden oder nicht dabei sind und im replacement gesetzt werden, sollte es dieser Ausdruck tun:

          ((?:'[^']*')|(?:"[^"]*"))

          cu,
          Andreas

          --
          Warum nennt sich Andreas hier MudGuard?
          O o ostern ...
          Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
          1. gruss Andreas,

            Back-References funktionieren m.W. nicht in Zeichenklassen.

            wahrscheinlich ist dem wirklich so, denn dies ist die einzig fuer
            mich nachvollziehbare ursache, die das verhalten aller bisherigen
            testcases wunderbar aufklaert und damit natuerlich auch die zuletzt
            praesentierte *loesung* als pseudoloesung entlarvt.

            bleiben also nur die vorgestellten muster fuer die einzeln zu
            betrachtenden faelle »nur '« sowie »nur "«, die sich dann aber
            mit der verketteten anwendungen zweier [replace] methoden doch
            noch als kombinierte loesung empfehlen.

            danke fuer die lektion - ich habe mich da richtig im dunkeln
            verrannt.

            so long - peterS. - pseliger@gmx.net

            --
            »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
            Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
            ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
            1. Hi,

              bleiben also nur die vorgestellten muster fuer die einzeln zu
              betrachtenden faelle »nur '« sowie »nur "«, die sich dann aber
              mit der verketteten anwendungen zweier [replace] methoden doch
              noch als kombinierte loesung empfehlen.

              Wieso zwei Replace-Methoden?

              Wenn die ' oder " erhalten bleiben sollen:, kann man einfach
              Suche nach:    ((?:'[^']*')|(?:"[^"]*"))
              Ersetze durch: LOWER(\1)
              Die ' bzw. " werden ja mit-gefangen.

              Wenn die ' oder " durch eine Sorte (z.B. immer ') ersetzt werden sollen:
              Suche nach:    (?:'([^'])*')|(?:"([^"])*")
              Ersetze durch: LOWER('\1\2')
              Denn entweder ist die erste Backreferenz gefüllt (bei '') und die zweite leer oder die erste leer (bei "") und die zweite gefüllt.

              cu,
              Andreas

              --
              Warum nennt sich Andreas hier MudGuard?
              O o ostern ...
              Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
              1. Hallo zusammen,

                das Problem mit den einzelnen Hochkommata und den doppelten ergibt sich bei mir nicht, da ich in dem sql statement ausschließlich einzelne Hochkomma habe, die es zu suchen gilt.
                Somit ist diese Lösung hier von Peter -->

                var regX = (/(['])([^\1]*?)\1/g);
                         whereStr = whereStr.replace(regX, "LOWER($1$2$1)");

                für mich wunderbar!
                Leider habe nur noch das Problem, dass natürlich Murks rauskommt, wenn in einem der Suchwerte wiederum ein einzelnes Hochkomma vorkommt
                --> str = "select Lower(col1) from table1 where col1 like 'b''%'";
                ergibt : select Lower(col1) from table1 where col1 like LOWER('b')LOWER('%')

                Aber ich glaube, aus der Nummer kommt man so nicht raus...

                Dennoch, vielen, vielen Dank für Eure Bemühungen!

                Gruss,

                BSF

                was zwar selten ist, aber vorkommen kann. Aber ich glaube, aus der Nummer kommt man so nicht raus...

                Hi,

                bleiben also nur die vorgestellten muster fuer die einzeln zu
                betrachtenden faelle »nur '« sowie »nur "«, die sich dann aber
                mit der verketteten anwendungen zweier [replace] methoden doch
                noch als kombinierte loesung empfehlen.

                Wieso zwei Replace-Methoden?

                Wenn die ' oder " erhalten bleiben sollen:, kann man einfach
                Suche nach:    ((?:'[^']*')|(?:"[^"]*"))
                Ersetze durch: LOWER(\1)
                Die ' bzw. " werden ja mit-gefangen.

                Wenn die ' oder " durch eine Sorte (z.B. immer ') ersetzt werden sollen:
                Suche nach:    (?:'([^'])*')|(?:"([^"])*")
                Ersetze durch: LOWER('\1\2')
                Denn entweder ist die erste Backreferenz gefüllt (bei '') und die zweite leer oder die erste leer (bei "") und die zweite gefüllt.

                cu,
                Andreas

                1. hallo again BSF,

                  das Problem mit den einzelnen Hochkommata und den doppelten ergibt sich bei
                  mir nicht, da ich in dem sql statement ausschließlich einzelne Hochkomma habe,
                  die es zu suchen gilt.

                  ... wissen wir doch schon lange, ich bin doch nur so grandios am generischen
                  ansatz gescheitert, der *eierlegendwollmichwasweisich* sein wollte, aber schon
                  die erste huerde nicht nehmen kann, weil »backreferences« in zeichenklassen nicht
                  zugelassen sind.

                  vergiss also _jedes_ in den beispielen gegebene suchmuster, welches mit »backreferences«
                  *arbeitet*.

                  Somit ist diese Lösung hier von Peter -->

                  var regX = (/(['])([^\1]*?)\1/g);
                           whereStr = whereStr.replace(regX, "LOWER($1$2$1)");

                  für mich wunderbar!

                  nein, nein und nein, denn die begruendung fuer einen verzicht genau darauf ...

                  Leider habe nur noch das Problem, dass natürlich Murks rauskommt, wenn in
                  einem der Suchwerte wiederum ein einzelnes Hochkomma vorkommt
                  --> str = "select Lower(col1) from table1 where col1 like 'b''%'";
                  ergibt : select Lower(col1) from table1 where col1 like LOWER('b')LOWER('%')

                  ... lieferst Du ja gerade selber.

                  Aber ich glaube, aus der Nummer kommt man so nicht raus...

                  doch, sowohl Andreas als auch ich, haben fuer dein einfaches problem schon
                  mehrfach loesungen gepostet, liess Dir doch nochmal aufmerksam die jeweiligen
                  erklaerungen durch.

                  z.b. stand der hier - /(')([^']*)'/g - zur debatte (C&P >> jconsole.com) ...

                  var str = "select xyz from table1 where col1 like 'a%' and col2 like 'b%' and col3 like \"xy%\" and col4 like 'ik%'";  
                  var regX = (/(')([^']*)'/g);  
                    
                  print(regX.test(str));  
                  print(str.replace(regX, "LOWER($1$2$1)"));
                  

                  ... funktioniert fuer Deine belange genau richtig und kann noch vereinfacht
                  werden (C&P >> jconsole.com):

                  var str = "select xyz from table1 where col1 like 'a%' and col2 like 'b%' and col3 like \"xy%\" and col4 like 'ik%'";  
                  var regX = (/('[^']*')/g);  
                    
                  print(regX.test(str));  
                  print(str.replace(regX, "LOWER($1)"));
                  

                  ich hoffe, ich habe wieder einigermassen ordnung in das von mir geschaffene
                  chaos gebracht.

                  so long - peterS. - pseliger@gmx.net

                  --
                  »Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies.
                  Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.« - Douglas Crockford
                  ie:( fl:) br:> va:( ls:& fo:) rl:) n3;} n4:} ss:} de:µ js:} mo:? zu:]
  3. Hi,

    Also z.B. hieraus --> "select xyz from table1 where col1 like 'a%' and col2 like 'b%'"
    soll folgendes werden --> "select xyz from table1 where col1 like LOWER('a%')
    and col2 like LOWER('b%')"

    Hm. Und wo ist der Sinn dahinter? LOWER('a%') unterscheidet sich nicht von 'a%'.

    Wenn Du
    LOWER(col1) LIKE 'a%'
    draus machen würdest, hätte das eher eine Auswirkung ...

    cu,
    Andreas

    --
    Warum nennt sich Andreas hier MudGuard?
    O o ostern ...
    Fachfragen unaufgefordert per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
    1. Hi,

      hm, okay, ich korrigiere :
      Aus --> "select xyz from table1 where lower(col1) like ('A%')";
      soll das werden --> "select xyz from table1 where lower(col1) like lower('A%')";

      Ich hoffe, das macht so mehr Sinn.

      Danke und Gruss,

      BSF

      Hi,

      Also z.B. hieraus --> "select xyz from table1 where col1 like 'a%' and col2 like 'b%'"
      soll folgendes werden --> "select xyz from table1 where col1 like LOWER('a%')
      and col2 like LOWER('b%')"

      Hm. Und wo ist der Sinn dahinter? LOWER('a%') unterscheidet sich nicht von 'a%'.

      Wenn Du
      LOWER(col1) LIKE 'a%'
      draus machen würdest, hätte das eher eine Auswirkung ...

      cu,
      Andreas