PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Fonction d'échappement pour les expressions régulières ou les modèles LIKE

Pour répondre à la question du haut :

Fonction d'échappement d'expression régulière

Commençons par une liste complète des caractères ayant une signification particulière dans l'expression régulière motifs :

!$()*+.:<=>?[\]^{|}-

Enveloppés entre parenthèses, la plupart d'entre eux perdent leur signification particulière - à quelques exceptions près :

  • - doit être le premier ou le dernier ou cela signifie une plage de caractères.
  • ] et \ doivent être échappés avec \ (dans le remplacement, aussi).

Après avoir ajouté des parenthèses de capture pour la référence arrière ci-dessous, nous obtenons ce modèle d'expression régulière :

([!$()*+.:<=>?[\\\]^{|}-])

En l'utilisant, cette fonction échappe tous les caractères spéciaux avec une barre oblique inverse (\ ) - supprimant ainsi la signification spéciale :

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$;

Ajouter PARALLEL SAFE (parce que c'est c'est ) dans Postgres 10 ou version ultérieure pour permettre le parallélisme des requêtes qui l'utilisent.

Démo

SELECT f_regexp_escape('test(1) > Foo*');

Renvoie :

test\(1\) \> Foo\*

Et tandis que :

SELECT 'test(1) > Foo*' ~ 'test(1) > Foo*';

renvoie FALSE , ce qui peut surprendre les utilisateurs naïfs,

SELECT 'test(1) > Foo*' ~ f_regexp_escape('test(1) > Foo*');

Renvoie TRUE comme il se doit maintenant.

LIKE fonction d'échappement

Pour être complet, le pendentif pour LIKE modèles, où seuls trois caractères sont spéciaux :

\%_

Le manuel :

Le caractère d'échappement par défaut est la barre oblique inverse mais un autre peut être sélectionné en utilisant le ESCAPE clause.

Cette fonction assume la valeur par défaut :

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$;

Nous pourrions utiliser le plus élégant regexp_replace() ici aussi, mais pour les quelques caractères, une cascade de replace() fonctions est plus rapide.

Encore une fois, PARALLEL SAFE dans Postgres 10 ou version ultérieure.

Démo

SELECT f_like_escape('20% \ 50% low_prices');

Renvoie :

20\% \\ 50\% low\_prices