Para responder à pergunta no topo:
Função de escape de expressão regular
Vamos começar com uma lista completa de caracteres com significado especial em expressão regular padrões:
!$()*+.:<=>?[\]^{|}-
Envolvidos em uma expressão de colchetes, a maioria deles perde seu significado especial - com algumas exceções:
-
precisa ser o primeiro ou o último ou significa um intervalo de caracteres.]
e\
tem que ser escapado com\
(na substituição também).
Depois de adicionar parênteses de captura para a referência de retorno abaixo, obtemos este padrão regexp:
([!$()*+.:<=>?[\\\]^{|}-])
Ao usá-lo, esta função escapa todos os caracteres especiais com uma barra invertida (
\
) - removendo assim o 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$;
Adicionar
PARALLEL SAFE
(porque é ) no Postgres 10 ou posterior para permitir o paralelismo para consultas que o utilizam. Demonstração
SELECT f_regexp_escape('test(1) > Foo*');
Devoluções:
test\(1\) \> Foo\*
E enquanto:
SELECT 'test(1) > Foo*' ~ 'test(1) > Foo*';
retorna
FALSE
, o que pode ser uma surpresa para usuários ingênuos, SELECT 'test(1) > Foo*' ~ f_regexp_escape('test(1) > Foo*');
Retorna
TRUE
como deveria agora. LIKE
função de escape
Para completar, o pingente para
LIKE
padrões, onde apenas três caracteres são especiais:\%_
O manual:
O caractere de escape padrão é a barra invertida, mas um diferente pode ser selecionado usando oESCAPE
cláusula.
Esta função assume o padrão:
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$;
Poderíamos usar o mais elegante
regexp_replace()
aqui também, mas para os poucos caracteres, uma cascata de replace()
funções é mais rápido. Novamente,
PARALLEL SAFE
no Postgres 10 ou posterior. Demonstração
SELECT f_like_escape('20% \ 50% low_prices');
Devoluções:
20\% \\ 50\% low\_prices