sql >> Base de Datos >  >> RDS >> PostgreSQL

Función de escape para expresiones regulares o patrones LIKE

Para abordar la pregunta en la parte superior:

Función de escape de expresiones regulares

Comencemos con una lista completa de caracteres con significado especial en expresión regular patrones:

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

Envueltos en una expresión entre paréntesis, la mayoría de ellos pierden su significado especial, con algunas excepciones:

  • - debe ser el primero o el último o significa un rango de personajes.
  • ] y \ tiene que ser escapado con \ (en el reemplazo, también).

Después de agregar paréntesis de captura para la referencia posterior a continuación, obtenemos este patrón de expresión regular:

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

Usándolo, esta función escapa todos los caracteres especiales con una barra invertida (\ ) - eliminando así el significado especial:

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

Agregar PARALLEL SAFE (porque es ) en Postgres 10 o posterior para permitir el paralelismo de las consultas que lo utilizan.

Demostración

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

Devoluciones:

test\(1\) \> Foo\*

Y mientras:

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

devuelve FALSE , que puede sorprender a los usuarios ingenuos,

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

Devuelve TRUE como debería ser ahora.

LIKE función de escape

Para completar, el colgante para LIKE patrones, donde solo tres caracteres son especiales:

\%_

El manual:

El carácter de escape predeterminado es la barra invertida, pero se puede seleccionar uno diferente usando ESCAPE cláusula.

Esta función asume el valor predeterminado:

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

Podríamos usar el más elegante regexp_replace() aquí también, pero para los pocos caracteres, una cascada de replace() funciones es más rápido.

De nuevo, PARALLEL SAFE en Postgres 10 o posterior.

Demostración

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

Devoluciones:

20\% \\ 50\% low\_prices