|
Antwort |
Registriert seit: 11. Okt 2003 Ort: Elbflorenz 44.184 Beiträge Delphi 12 Athens |
#1
Moin,
bis gestern funktionierte ein RegEx und dann urplötzlich nicht mehr und ich weiß nicht warum und keine hat (angeblich) an den Settings gespielt. Nur ein Kollege am Sprach-/Datumsformat des Servers, um was zu Testen, aber auch ein Zurücksetzen half natürlich nichts. Und das Neustarten des Server/DBServer brachte auch nichts. Was ich endlich rausfand ist, daß Zeilenumbrüche und \s sich im Verhalten verändert haben. Modifier sind nur "mi" (MultiLine und CaseInsensitive)
SQL-Code:
Also, das erste ^ findet noch einen Zeilenumbruch, \s trifft plözlich auch Zeilenumgrüche, obwohl z.B. der Modifier "s" (SingleLine) nicht angegeben ist.
CREATE OR REPLACE FUNCTION INI_GetValue(ini TEXT, section VARCHAR, name VARCHAR, defvalue VARCHAR DEFAULT '') RETURNS VARCHAR AS $$
-- SELECT+regexp_matches liefert "keinen" Datensatz, wenn nichts gefunden wurde, daher das SUBSELECT mit COALESCE SELECT nullif(coalesce((SELECT (regexp_matches(ini, '^\\[' || section || '\\]\\s*$[^\\[]*^' || name || '=(.*)$', 'mi'))[1]), defvalue), '') $$ LANGUAGE SQL IMMUTABLE; und weitere ^ oder $ treffen keinen Zeilenumbruche im Text mehr. Die Doppelten \\ sind korrect, da es ja einmal das Escape von Postgres und dann nochmal vom RegEx ist. Allerdings ging es bis gestern noch, daß ich in Postgres die \ nicht brauchte, wenn es keinen "Steuerbefehl" ergab, also z.B. kein Buchstabe folgte, womit auch '\[xxx\]' den Abschnitt traf und heute nur noch '\\[xxx\\]' funktioniert.
Code:
mit "^\[xxx\]\s*$[^\[]*^bbb=(.*)$" und "mi" sollte "ok" im ersten Match liefern.
[zzz]
bbb=nee [xxx] aaa=nee bbb=ok ccc=nee https://regex101.com/r/uQ4aP9/1 Mein aktueller "Lösungsansatz" gefällt mir so garnicht, voralem da man im RegEx danach garnicht mehr erkennt, was der macht.
Ich hatte einfach nur versucht vorhandene "Funktionen" endlich mal in Funktionen zu packen und als ich fertig war und es testen wollte, da ging es anfangs und dann mittendrin plötzlich nicht mehr.
SQL-Code:
Ein paar kleine "Bugs" gibt es zusätzlich noch, denn $[^\[]*^
ist falsch, da es nicht "Alles außer [" sondern "Alles außer wenn [ am Zeilenanfang" heißen müsste,
--value = INI_GetValue(ini, section, name, [defvalue])
--ini = INI_SetValue(ini, section, name, value) --value = SL_GetValue(list, name, [defvalue]) --list = SL_SetValue(list, name, value) CREATE OR REPLACE FUNCTION INI_GetValue(ini TEXT, section VARCHAR, name VARCHAR, defvalue VARCHAR DEFAULT '') RETURNS VARCHAR AS $$ -- SELECT+regexp_matches liefert "keinen" Datensatz, wenn nichts gefunden wurde, daher das SUBSELECT mit COALESCE SELECT nullif(coalesce((SELECT (regexp_matches(ini, '^\\[' || section || '\\]\\s*$[^\\[]*^' || name || '=(.*)$', 'mi'))[1]), defvalue), '') $$ LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION INI_SetValue(ini TEXT, section VARCHAR, name VARCHAR, value VARCHAR) RETURNS TEXT AS $$ DECLARE seA TEXT; seN TEXT; BEGIN -- altes weg ... der Lookbehind will nicht, wie er soll, als erst Section extrahieren und dann darin den Value entferen --ini := regexp_replace(ini, '(?<!^\\[' || section || '\\]\\s*$[^\\[]*)^' || name || '=(.*)$', '', 'mi'); seA := (regexp_matches(ini, '^\\[' || section || '\\]\\s*$[^\\[]*^' || name || '=(.*)$', 'mi'))[0]; seN := regexp_replace(seA, '^' || name || '=(.*)$', '', 'mi'); ini := replace(ini, seA, seN); -- neues rein IF regexp_matches(ini, '^\\[' || section || '\\]\\s*$', 'mi') IS NULL THEN ini := concat(ini, '\r\n[', section, ']'); END IF; IF (value <> '') and (value IS DISTINCT FROM defvalue) THEN ini := regexp_replace(ini, '^\\[' || section || '\\]\\s*$', concat('[', section, ']\r\n', name, '=', value), 'mi'); END IF; -- fertig return ini; END $$ LANGUAGE plpgsql; CREATE OR REPLACE FUNCTION SL_GetValue(list TEXT, name VARCHAR, defvalue VARCHAR DEFAULT '') RETURNS VARCHAR AS $$ -- SELECT+regexp_matches liefert "keinen" Datensatz, wenn nichts gefunden wurde, daher das SUBSELECT mit COALESCE SELECT nullif((SELECT (regexp_matches(list, '^' || name || '=(.*)$', 'mi'))[1]), '') $$ LANGUAGE SQL IMMUTABLE; CREATE OR REPLACE FUNCTION SL_SetValue(list TEXT, name VARCHAR, value VARCHAR) RETURNS TEXT AS $$ BEGIN -- altes weg list := regexp_replace(list, '=(.*)$', '', 'mi'); -- neues rein IF (value <> '') and (value IS DISTINCT FROM defvalue) THEN list := concat(list, '\r\n', name, '=', value); END IF; -- sortieren return trim(array_to_string(ARRAY(SELECT regexp_split_to_table(list, '\r?\n' , 'mi') ORDER BY 1), '\r\n')' \r\n'); END $$ LANGUAGE plpgsql; -- Test = [zzz]\nbbb=nee\n[xxx]\naaa=nee\nbbb=ok\nccc=nee -- Test2 = aaa=nee\nbbb=ok\nccc=nee SELECT INI_GetValue(GetSetting('Test'), 'xxx', 'bbb') SELECT SL_GetValue(GetSetting('Test2'), 'bbb') aber k.A. wie das gehn soll, da Lookarounds keine .* drin haben wollen.
$2B or not $2B
Geändert von himitsu (12. Jul 2016 um 11:52 Uhr) |
Zitat |
Registriert seit: 11. Okt 2003 Ort: Elbflorenz 44.184 Beiträge Delphi 12 Athens |
#2
Hab zwar immernoch keine Ahnung, was das Problem ist , aber zumindestens hab ich erstmal wider eine funktionierende Version.
SQL-Code:
-- INI-TEXT und StringList-TEXT (Name=Value) in der DB behandeln
-- line = SL_GetLine (list, index) -- value = SL_GetValue(list, name, [defvalue]) -- list = SL_SetValue(list, name, value, [defvalue]) -- value = INI_GetValue(ini, section, name, [defvalue]) -- ini = INI_SetValue(ini, section, name, value, [defvalue]) -- Initial : SELECT SetSetting('Test', 'aaa=nee\r\nbbb=ok\r\nccc=nee'), SetSetting('Test2', '[zzz]\r\nbbb=nee\r\n[xxx]\r\naaa=nee\r\nbbb=ok\r\nccc=nee') -- SL-Test : SELECT GetTextSetting('Test'), SL_GetValue(GetSetting('Test'), 'bbb'), SL_SetValue(GetSetting('Test'), 'bbb', 'NEU'), SL_SetValue(GetSetting('Test'), 'bbc', 'NEU') -- SL-Test2 : SELECT GetTextSetting('Test'), SL_GetLine(GetSetting('Test'), 1), SL_GetLine(GetSetting('Test'), 3), SL_GetLine(GetSetting('Test'), 4) -- INI-Test : SELECT GetTextSetting('Test2'), INI_GetValue(GetSetting('Test2'), 'xxx', 'bbb'), INI_SetValue(GetSetting('Test2'), 'xxx', 'bbb', 'NEU'), INI_SetValue(GetSetting('Test2'), 'xxx', 'bbc', 'NEU') -- Zeile aus einem StringList-TEXT auslesen CREATE OR REPLACE FUNCTION SL_GetLine(list TEXT, line INTEGER) RETURNS VARCHAR AS $$ --SELECT (regexp_matches(list, '^(.*)$', 'm'))[line] SELECT (regexp_split_to_array(list, '\\r?\\n'))[line] $$ LANGUAGE SQL IMMUTABLE; -- -- Value aus einem StringList-TEXT auslesen -> Name=Value CREATE OR REPLACE FUNCTION SL_GetValue(list TEXT, name VARCHAR, defvalue VARCHAR DEFAULT '') RETURNS VARCHAR AS $$ -- SELECT+regexp_matches liefert "keinen" Datensatz, wenn nichts gefunden wurde, daher das SUBSELECT mit COALESCE SELECT coalesce((SELECT (regexp_matches(list, '^' || name || '=(.*)$', 'mi'))[1]), defvalue) $$ LANGUAGE SQL IMMUTABLE; -- -- Value in einem StringList-TEXT ändern -> Name=Value CREATE OR REPLACE FUNCTION SL_SetValue(list TEXT, name VARCHAR, value VARCHAR, defvalue VARCHAR DEFAULT '') RETURNS TEXT AS $$ BEGIN -- altes weg list := regexp_replace(list, '^' || name || '=(.*)$', '', 'mi'); -- neues rein IF (value <> '') and (value IS DISTINCT FROM defvalue) THEN list := concat(list, '\r\n', name, '=', value); END IF; -- sortieren RETURN trim(array_to_string(ARRAY(SELECT regexp_split_to_table(list, '\r?\n' , 'mi') ORDER BY 1), '\r\n'), ' \r\n'); END $$ LANGUAGE plpgsql; -- -- Value aus einem INI-TEXT auslesen -> [Section] Name=Value CREATE OR REPLACE FUNCTION INI_GetValue(ini TEXT, section VARCHAR, name VARCHAR, defvalue VARCHAR DEFAULT '') RETURNS VARCHAR AS $$ -- SELECT+regexp_matches liefert "keinen" Datensatz, wenn nichts gefunden wurde, daher das SUBSELECT mit COALESCE --SELECT coalesce((SELECT (regexp_matches(ini, '^\\[' || section || '\\]\\s*$[^\\[]*^' || name || '=(.*)$', 'mi'))[1]), defvalue) -- Aus unerfindlichen Gründen funktioniert das Zeilenendematching nicht mehr, daher manuell die Zeilenumbrüche suchen http://www.delphipraxis.net/189708-regex-fehlerhafter-zeilenumbruch-postgresql.html SELECT coalesce((SELECT (regexp_matches('\\n' || ini || '\\n', '\\r?\\n\\[' || section || '\\][ \\t]*\\r?\\n?[^\\[]*\\r?\\n' || name || '=([^\\r\\n]*)\\r?\\n', 'i'))[1]), defvalue) $$ LANGUAGE SQL IMMUTABLE; -- -- Value in einem INI-TEXT ändern -> [Section] Name=Value CREATE OR REPLACE FUNCTION INI_SetValue(ini TEXT, section VARCHAR, name VARCHAR, value VARCHAR, defvalue VARCHAR DEFAULT '') RETURNS TEXT AS $$ DECLARE seA TEXT; seN TEXT; BEGIN /* -- altes weg ... der Lookbehind will nicht, wie er soll, also zuerst Section extrahieren und dann darin den Value entferen --ini := regexp_replace(ini, '(?<!^\\[' || section || '\\]\\s*$[^\\[]*)^' || name || '=(.*)$', '', 'mi'); seA := (regexp_matches(ini, '^(\\[' || section || '\\]\\s*$[^\\[]*^' || name || '=.*)$', 'mi'))[0]; seN := regexp_replace(seA, '^' || name || '=.*$', '', 'mi'); IF seA <> '' THEN ini := replace(ini, seA, seN); END IF; -- neues rein IF regexp_matches(ini, '^\\[' || section || '\\]\\s*$', 'mi') IS NOT NULL THEN ELSE ini := concat(ini, '\r\n[', section, ']'); END IF; IF (value <> '') and (value IS DISTINCT FROM defvalue) THEN ini := regexp_replace(ini, '^\\[' || section || '\\]\\s*$', concat('[', section, ']\r\n', name, '=', value), 'mi'); END IF; -- fertig RETURN trim(regexp_replace(ini, '\\r?\\n([ \\t]*\\r?\\n)+', '\r\n', ''), ' \r\n'); */ -- Aus unerfindlichen Gründen funktioniert das Zeilenendematching nicht mehr, daher manuell die Zeilenumbrüche suchen http://www.delphipraxis.net/189708-regex-fehlerhafter-zeilenumbruch-postgresql.html ini := '\n' || ini || '\n'; -- altes weg seA := (regexp_matches(ini, '(\\r?\\n\\[' || section || '\\][ \\t]*\\r?\\n?[^\\[]*\\r?\\n' || name || '=([^\\r\\n]*)\\r?\\n)', 'i'))[1]; seN := regexp_replace(seA, '^' || name || '=.*$', '', 'mi'); IF seA <> '' THEN ini := replace(ini, seA, seN); END IF; -- neues rein IF regexp_matches(ini, '\\r?\\n\\[' || section || '\\][ \\t]*\\r?\\n', 'i') IS NOT NULL THEN ELSE ini := concat(ini, '\r\n[', section, ']\r\n'); END IF; IF (value <> '') and (value IS DISTINCT FROM defvalue) THEN ini := regexp_replace(ini, '\\r?\\n\\[' || section || '\\][ \\t]*\\r?\\n', concat('\r\n[', section, ']\r\n', name, '=', value, '\r\n'), 'i'); END IF; -- fertig RETURN trim(regexp_replace(ini, '\\r?\\n([ \\t]*\\r?\\n)+', '\r\n', ''), ' \r\n'); END $$ LANGUAGE plpgsql; -- --
$2B or not $2B
|
Zitat |
Ansicht |
Linear-Darstellung |
Zur Hybrid-Darstellung wechseln |
Zur Baum-Darstellung wechseln |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
LinkBack URL |
About LinkBacks |