RegExp
BSF
- javascript
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,
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.
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
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
>
>
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
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
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
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
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
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
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
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