Om de vraag bovenaan te beantwoorden:
Reguliere expressie-escape-functie
Laten we beginnen met een volledige lijst van tekens met een speciale betekenis in gewone uitdrukking patronen:
!$()*+.:<=>?[\]^{|}-
Verpakt tussen haakjes, verliezen de meeste van hen hun speciale betekenis - met een paar uitzonderingen:
-
moet de eerste of laatste zijn of het betekent een bereik van karakters.]
en\
moeten worden geëscaped met\
(ook in de vervanging).
Na het toevoegen van haakjes voor de back-referentie hieronder krijgen we dit regexp-patroon:
([!$()*+.:<=>?[\\\]^{|}-])
Door het te gebruiken, ontsnapt deze functie aan alle speciale tekens met een backslash (\
) - waardoor de speciale betekenis wordt verwijderd:
CREATE OR REPLACE FUNCTION f_regexp_escape(text)
RETURNS text
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS
$func$
SELECT regexp_replace($1, '([!$()*+.:<=>?[\\\]^{|}-])', '\\\1', 'g')
$func$;
PARALLEL SAFE
toevoegen (omdat het is ) in Postgres 10 of later om parallellisme toe te staan voor query's die het gebruiken.
Demo
SELECT f_regexp_escape('test(1) > Foo*');
Retourneren:
test\(1\) \> Foo\*
En terwijl:
SELECT 'test(1) > Foo*' ~ 'test(1) > Foo*';
retourneert FALSE
, wat voor naïeve gebruikers als een verrassing kan komen,
SELECT 'test(1) > Foo*' ~ f_regexp_escape('test(1) > Foo*');
Retourneert TRUE
zoals het nu zou moeten.
LIKE
ontsnappingsfunctie
Voor de volledigheid, de hanger voor LIKE
patronen, waar slechts drie tekens speciaal zijn:
\%_
De handleiding:
Het standaard escape-teken is de backslash, maar een andere kan worden geselecteerd met behulp van de
ESCAPE
clausule.
Deze functie neemt de standaardwaarde aan:
CREATE OR REPLACE FUNCTION f_like_escape(text)
RETURNS text
LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS
$func$
SELECT replace(replace(replace($1
, '\', '\\') -- must come 1st
, '%', '\%')
, '_', '\_');
$func$;
We zouden de elegantere regexp_replace()
kunnen gebruiken hier ook, maar voor de paar tekens, een cascade van replace()
functies is sneller.
Nogmaals, PARALLEL SAFE
in Postgres 10 of later.
Demo
SELECT f_like_escape('20% \ 50% low_prices');
Retourneren:
20\% \\ 50\% low\_prices