Suchen + Ersetzen eines Strings der u.a. eckige Klammern enthält

Hallo zusammen,
kurz vorweg, ich habe hier ein PostgreSQL 8.4 vorgegeben. Ich selber habe kaum Erfahrung mit postgresql Datenbanken. Mit SQL an sich schlage ich mich aber auf einfachem Level schon eine Weile rum. Ich hänge hier leider auch so in der Luft, weil ich für diesen Fall mit den ganzen eckigen Klammern im String etc. kein passendes oder für mich widersprüchliche und für mich so nicht funktionierende Beispiel gefunden habe. Das Handbuch (PostgreSQL: Documentation: 8.4: Lexical Structure ) hat mir in dem Fall auch nicht viel weiter geholfen. Liegt warscheinlich an der mangelnden Erfahrung, das ich da was für mich wichtiges überlese/ nicht verstehe.

Das Problem:
ich muss in der Datenbank diverse Datensätze korrigieren. Diese Datensätze beinhalten jeweils eine Seite/Page wie auch immer eines CMS/Intranet-Systems. Ein Update dieser Software zieht es leider nach sich, das ich sehr viele Änderungen am Layout direkt über SQL Abfragen machen muss. Schon viel erledigt, aber an dieser korrektur beiß ich mir die Zähne aus:

IST:

<ac :p lain-text-body>[CDATA[Neues ToDo ...]]</ac :p lain-text-body><

SOLL:

<ac :p lain-text-body><![CDATA[Neues ToDo ...]]></ac :p lain-text-body><

Ich habe schon verstanden, das SQL mit den eckigen Klammern im String ein Problem hat und habe versucht das über E’’ und entsprechende Backslashes zu vermeiden.

Mein Lösungsansatz sieht bisher wie folgt aus:

    UPDATE bodycontent SET body = REPLACE(body,E'<ac :p lain-text-body>\[CDATA\[Neues ToDo ...\]\]</ac :p lain-text-body>',E'<ac :p lain-text-body><!\[CDATA\[Neues ToDo ...\]\]></ac :p lain-text-body>');

Nur leider funktioniert das nicht. Irgendwo habe ich da einen Denkfehler drin.

Ich habe auch schon versucht über SELECT Anweisungen die Schreibweise zu überprüfen.

    SELECT bodycontent.body FROM bodycontent WHERE bodycontent.body ~ E'<ac :p lain-text-body>\[CDATA\[Neues ToDo ...\]\]</ac :p lain-text-body>';

Hier habe ich aber eher ALLE Seiten als Treffer, als die, in dennen “[CDATA[Neues ToDo …]] …” steht. Das der Select Befehl nicht funktioniert schein aber daran zu liegen, das hier eine RegEx Abfrage (~) vorliegt und ich so wahrscheinlich eine recht Interessante Abfrage in an die DB schicke, die aber überhaupt nichts mit dem zu tun hat was sich möchte.


Wie auch immer:

Kann mir jemand schreiben, wo bei der UPDATE Abfrage mein Denkfehler liegt bzw. ein Beispiel geben?

Keine fertige Lösung, aber: ich denke, du solltest Dir regexp_replace() anschauen, PostgreSQL: Documentation: 9.1: Pattern Matching , sollte in 8.4 auch gehen.


Andreas

Danke, gibt es auch unter 8.4 -> regexp_replace(source, pattern, replacement [, flags ])
Ich hab das jetzt mal in zwei Teile zerlegt, einmal vorne das “<!” und einmal hinten das “>” einfügen. Ist für mich erstmal einfacher nach zu vollziehen.

UPDATE bodycontent SET body = regexp_replace('<ac :p lain-text-body>[CDATA[Neues ToDo ...]]</ac :p lain-text-body><', '((?<=\<ac\ :p lain-text-body\>)(?=\[CDATA\[.+\]\]))' , '<!')

UPDATE bodycontent SET body = regexp_replace('<ac :p lain-text-body>[CDATA[Neues ToDo ...]]</ac :p lain-text-body><', '((?<=.+\]\])(?=</ac :p lain-text-body>)' , '>')

Bin mir nur noch nicht sicher mit der source Angabe. Ich muss ja bestimmt Tabelle(bodycontent) und Spalte(body) angeben, in dem die Ersetzung stattfinden soll + der Part

<ac :p lain-text-body>[CDATA[Neues ToDo ...]]</ac :p lain-text-body><

ist ja auch nur ein bestimmter Abschnitt im Datensatz. Muss ich bei source dann die Spalte angeben oder wäre meine Variante trotzdem Richtig?

Ja klar, Du holst das aus der Tabelle, änderst es, fügst es wieder ein. Mach Dir vorher eine Kopie, oder teste es an einer Kopie.


Andreas

Komm mir gerade vor, wie der erste Mensch bei der Hitze ^^.

also quasi so:

UPDATE bodycontent SET body = regexp_replace(body, '((?<=.+\]\])(?=</ac :p lain-text-body>)' , '>')

wobei “body” die spalte ist?

Tja das mit den Kopien, ich zieh hier seit das mit dem verbuggtem Upgrade läuft recht häufig vor solchen UPDATE Orgien kopien :slight_smile: . Aber danke für den Hinweis, früher hab ich das gern mal vergessen :wink: .

Gruß Anastasiuss

[EDIT]:

Bei

UPDATE bodycontent SET body = regexp_replace(body, '((?<=.+\]\])(?=</ac :p lain-text-body>)' , '>')

bekomme ich jetzt die folgende Warnung

WARNUNG:  nicht standardkonforme Verwendung von Escape in Zeichenkettenkonstante
LINE 1: ...PDATE bodycontent SET body = regexp_replace(body, '((?<=\<ac...
                                                             ^
HINT:  Verwenden Sie die Syntax für Escape-Zeichenketten, z.B. E'\r\n'.


FEHLER:  ungültiger regulärer Ausdruck: quantifier operand invalid

********** Fehler **********

FEHLER: ungültiger regulärer Ausdruck: quantifier operand invalid
SQL Status:2201B

Ich habe es also angepasst:

UPDATE bodycontent SET body = regexp_replace(body, E'((?<=\<ac\ :p lain-text-body\>)(?=\[CDATA\[.+\]\]))' , '<!');
UPDATE bodycontent SET body = regexp_replace(body, E'((?<=.+\]\])(?=</ac :p lain-text-body>)' , '>');

jetzt kommt der Fehler:

FEHLER:  ungültiger regulärer Ausdruck: quantifier operand invalid

********** Fehler **********

FEHLER: ungültiger regulärer Ausdruck: quantifier operand invalid
SQL Status:2201B

Ich könnte mir nurvorstellen, das es wegen ?= bzw ?>= ist. Also lookahead / behind assertion. PostgreSQL: Documentation: 8.4: Pattern Matching
Hier ließt sich das in tabelle 9.14 aber so, als ob Postgresql das unterstützt.

Irgendwie dreh ich mich im Kreis, jetzt steh ich letztendlich wieder vor dem Problem mit dem E’ ’ bzw. weiß ich nicht, wie und wo ich die Backslashes richtig setzen soll, das die Abfrage funktioniert.

Ich such mir ja viel selber zusammen, aber ich bräuchte hier doch nen deutlicheren Schupser, bzw. Beispiel… und ne Klimaanlage …

Danke schonmal im Voraus :slight_smile:

Nachtigal ick hör dir trapsen …

kann es sein, das PG lookahead unterstützt (?=) aber nicht lookbehind (?<=) Das würde sehr viel klären :slight_smile: Table Table 9-14. Regular Expression Constraints im Hanbdbuch
Wobei ich mir dann einen komplett neuen Lösungsansatz suchen müsste…


Ich hab jetzt die Abfrage mal weiter zusammengefasst und wiederangepasst. Diesmal ohne jegliche ‘looks’:

UPDATE bodycontent SET body = regexp_replace(body, E'plain-text-body\\>\\[CDATA' , E'plain-text-body\\>\\<!\\[CDATA');

Nur findet er jetzt keine Treffer mehr, obwohl sich definitiv Datensätze mit Inhalt

SELECT bodycontent.body FROM bodycontent WHERE bodycontent.body ~ E'plain-text-body\\>\\[CDATA';

“plain-text-body>[CDATA” in der Tabelle body befinden.

ich wieder, komme ja irgendwie nich voran.

Versuche mich gerade an einer anderen Ecke, mit der gleichen Problemstellung der eckigen Klammern und Sonderzeichen (Eckige klammern !, <> etc…) in den Textabschnitten die ersetzt werden sollen.

IST

<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac :p arameter   ac:name="atlassian-macro-output-type">BLOCK</ac :p arameter><ac :p lain-text-body><=!=[=C=D=A=T=A=[{dynamictasklist:Sofortmaßnahmen}

SOLL

<ac:macro ac:name="tasklist"><ac :p arameter  ac:name="title">Sofortmaßnahmen</ac :p arameter><ac :p arameter  ac:name="atlassian-macro-output-type">BLOCK</ac :p arameter><ac :p lain-text-body><=!=[=C=D=A=T=A=[

UPDATE Query

    UPDATE bodycontent SET body = REPLACE(body,E'<ac:macro ac:name="unmigrated-inline-wiki-markup"><ac :p arameter ac:name="atlassian-macro-output-type">BLOCK</ac :p arameter><ac :p lain-text-body><!\[CDATA\[{dynamictasklist:Sofortmaßnahmen}',E'<ac:macro ac:name="tasklist"><ac :p arameter ac:name="title">Sofortmaßnahmen</ac :p arameter><ac :p arameter ac:name="atlassian-macro-output-type">BLOCK</ac :p arameter><ac :p lain-text-body><!\[CDATA\[');

Also, wenn ich mir das so ansehe, ich würd’s wahrscheinlich doch lieber in php abhandeln, einlesen aus der DB, mit preg_replace o.ä. umwandeln, zurückschreiben. Da funktionieren die ganzen Standard-regexe. Wenn Du bei Unix/Linux bist oder die unixtools installiert hast, kannst Du es wahrscheinlich sogar mit einem bash-script und sed einfacher haben, denke ich.

just my 2ct

cu jth

php ist nen guter hinweis ,ich versuch mich mal dran… Unix wär schön gewesen :slight_smile:

Unix … wenn Du psql dabei hast (Linux hat das, wenn man postgres installiert) kannst Du damit perfekt in der Bash arbeiten:

psql -c dbname username

kannst Du von der Kommandozeile aus aufrufen, man psql ist (zumindest bei postgres 9.3) recht ordentlich. Du kannst auch ganze Scriptdateien abarbeiten lassen (-f ).

Ich mach z.B. sowas:

QRY="update db set dflexdbfields = '$dflexdbfields', dflexdbftypes = '$dflexdbftypes' where upper(dflexname)=upper('$1');"
result=`psql -t -U pgdvs -d pgdvs -c "$QRY" 2>/dev/null | tr -d '\n '`

, wobei $dflexdbfields, $dflexdbftypes und $1 Bash-Variablen sind.

cu jth

Wann ist denn Version 9.3 erschienen?

Sorry, Blödsinn, ist 9.07, hab was velwechsert…

cu jth