0

如何在 Oracle 中转义正则表达式模式的特殊字符?

例如,我需要一个可以翻译的函数

some.string[with(special)reg-exp]characters

some\.string\[with\(special\)reg\-exp\]characters.

在 PHP 中我会使用 preg_escape()。有Oracle对应的吗?

我为什么要这样做?

我正在尝试编写一个 pl/sql 函数来检查 astring是否在list,of,string,elements.

这是我的代码:

CREATE OR REPLACE 
FUNCTION list_contains(needle_    IN VARCHAR2,
                       haystack_  IN VARCHAR2,
                       separator_ IN VARCHAR2 DEFAULT ',')
RETURN INTEGER
  IS
BEGIN
  IF regexp_like(haystack_, '(^|' || separator_ || ')' || needle_ || '(' || separator_ || '|$)') THEN
    RETURN 1;
  ELSE
    RETURN 0;
  END IF;
END list_contains;

该功能基本有效:

list_conains('eve','john,eve,maria,steve') => 1

问题是当我尝试用needle_or的奇怪值来调用它时separator_,例如.在正则表达式中具有特殊含义的其他字符串。

list_conains('eve','john.maria.steve','.') => 1

如您所见,列表中没有 eve,但.匹配tsteve 姓名的字母,因此函数错误地返回1

我知道我可以手动替换这些点,但是仍然有很多其他正则表达式特殊字符会干扰,我不想自己尝试列出所有字符。

如何逃脱needle_和separator_?

4

5 回答 5

2

如果我正确理解你的问题,你不需要正则表达式。您可以使用简单的 LIKE。

IF separator_ || haystack_ || separator_ LIKE '%'||separator_||needle_||separator_||'%' THEN
   RETURN 1;
ELSE
   RETURN 0;
END IF;

编辑:如果%_本身是 separator_,那么有必要将它们转义。

IF separator_ = '%' OR separator_ = '_'
THEN
  separator_ := '\' || separator_;
END IF;

IF separator_ || haystack_ || separator_ LIKE
     '%' || separator_ || needle_ || separator_ || '%' ESCAPE '\'
THEN
  RETURN 1;
ELSE
  RETURN 0;
END IF;
于 2013-09-20T12:10:03.727 回答
1

以下字符必须转义: \ ^ 。$ | ( ) [ ] * + ? { } ,

http://psoug.org/snippet/Regular-Expressions--Regexp-Cheat-Sheet_856.htm

SELECT REGEXP_REPLACE('some.string[with(special)reg-exp]characters', '([][)(}{.$*+?,|^\])', '\\\1') "REGEXP_REPLACE" FROM dual;
于 2013-12-05T17:54:53.623 回答
0

我认为在正则表达式语句中转义分隔符可能是最简单的。试试这个,它似乎对我有用:

  IF regexp_like(haystack_, '(^|\' || separator_ || ')' || needle_ || '(\' || separator_ || '|$)') THEN

我改变的只是字符串结构中分隔符前面的斜线。

于 2013-09-20T14:10:57.573 回答
0

尝试这个:

CREATE OR REPLACE 
FUNCTION list_contains(needle_    IN VARCHAR2,
                       haystack_  IN VARCHAR2,
                       separator_ IN VARCHAR2 DEFAULT ',')
return number AS
  l_return_count number := 0;
BEGIN
  with haystack_ary as (
    select extractvalue(x.column_value, 'e') as val
    from xmltable ('e' passing xmlparse( content  '<e>' || replace(haystack_, separator_, '</e><e>') || '</e>')) x
  )
  select 
  --count(1)
  --return as a "bool"(1=true,0=false)
  decode(count(1), 0, 0, 1)
  into l_return_count
  from haystack_ary
  where lower(needle_) = lower(haystack_ary.val);

  return l_return_count;
END;

我用较低的功能使它不区分大小写。如果你愿意,你也可以修剪空白: lower(trim(needle_)) = lower(trim(haystack_ary.val))

于 2013-09-20T14:17:04.967 回答
0

这可以在没有任何正则表达式的情况下完成,并通过instr函数转义,如果不匹配则返回 0 ,如果匹配则返回> 0

为此,您应该在needle_haystack_的开头和结尾添加separator_ ,然后再检查haystack_是否包含needle_

概念证明

select haystack_, needle_, separator_, instr(separator_||haystack_||separator_, separator_||needle_||separator_) result_, expected_
from (
    select 'john,eve,maria,steve' as haystack_ , 'eve' as needle_, ',' as separator_, '>0'as expected_ from dual union all
    select 'john,eve,maria,steve' as haystack_ , 'john' as needle_, ',' as separator_, '>0'as expected_ from dual union all
    select 'john,eve,maria,steve' as haystack_ , 'joh' as needle_, ',' as separator_, '=0'as expected_ from dual union all
    select 'john,eve,maria,steve' as haystack_ , 'steve' as needle_, ',' as separator_, '>0'as expected_ from dual union all
    select 'john,eve,maria,steve' as haystack_ , 'stev' as needle_, ',' as separator_, '=0'as expected_ from dual union all
    select 'john,eve,maria,steve' as haystack_ , 'teve' as needle_, ',' as separator_, '=0'as expected_ from dual union all
    select 'john.maria.steve' as haystack_ , 'eve' as needle_, '.' as separator_, '=0'as expected_ from dual union all
    select 'john_maria_steve' as haystack_ , 'eve' as needle_, '_' as separator_, '=0'as expected_ from dual union all
    select 'john%maria%steve' as haystack_ , 'eve' as needle_, '%' as separator_, '=0'as expected_ from dual
) t;

结果:

HAYSTACK_            NEEDLE_ SEPARATOR_ RESULT_ EXPECTED_
john,eve,maria,steve eve     ,          6       >0
john,eve,maria,steve john    ,          1       >0
john,eve,maria,steve joh     ,          0       =0
john,eve,maria,steve steve   ,          16      >0
john,eve,maria,steve stev    ,          0       =0
john,eve,maria,steve teve    ,          0       =0
john.maria.steve     eve     .          0       =0
john_maria_steve     eve     _          0       =0
john%maria%steve     eve     %          0       =0
于 2019-02-06T10:53:41.627 回答