SQL REGEX 没有像预期的那样工作

SQL REGEX not working like its expected to

我在寻找解决方案时遇到问题

set serveroutput on;
declare
EmailRegexp CONSTANT VARCHAR2(1000) :='^[a-z0-9!#$%&''*+/=?^_`{|}~-]+(\.[a-z0-9!#$%&''*+/=?^_`{|}~-]+)*@([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+([A-Z]{2,})$';
p_vInEmailAddress VARCHAR2(30) := 'first@hotmail.net';

begin 
dbms_output.put_line('regex: '||LOWER(SUBSTR(REGEXP_SUBSTR(p_vInEmailAddress, '\.([^.\n\s]*)$'), 2))||''''); 
end;

--results:
--regex: '
--PL/SQL procedure successfully completed.

--now if i do this instead: 
p_vInEmailAddress VARCHAR2(30) := 'first@hotmail.com';
--I get results back

--PL/SQL procedure successfully completed.

--regex: com'

我哪里做错了,为什么它不喜欢“.net”部分?

我该如何解决这个问题?

谢谢

您的查询中有问题的部分可以简化为:

begin 
  dbms_output.put_line(
    REGEXP_SUBSTR(
      'first@hotmail.net',
      '\.([^.\n\s]*)$'
    )
  ); 
end;
/

正则表达式\.([^.\n\s]*)$正在寻找:

  1. 一个点字符\.;然后
  2. 零个或多个不是点 . 或斜线 \n 或斜线 \ 或 [=19= 的字符];然后
  3. 字符串结尾。

问题是你的字符串有一个 n 字符并且正则表达式排除了 n 因为 \n 被解释为两个字符而不是代表一个的类似 perl 的表达式单个换行符。您想要将 \n 替换为字符串文字外部的 CHR(10) 字符(或其中的换行符),并将 \s 替换为 posix 表达式 [:space:].

你想要的是:

begin 
  dbms_output.put_line(
    REGEXP_SUBSTR(
      'first@hotmail.net',
      '\.([^.' || CHR(10) || '[:space:]]*)$'
    )
  ); 
end;
/

begin 
  dbms_output.put_line(
    REGEXP_SUBSTR(
      'first@hotmail.net',
      '\.([^.
[:space:]]*)$'
    )
  ); 
end;
/

db<>fiddle here

只需使用

REGEXP_SUBSTR(p_vInEmailAddress,'\.([^.[:space:]]*)$')

\s 与 Oracle 正则表达式中字符 class 中的空格不匹配。

[:space:] 匹配水平和垂直空格。

解释

--------------------------------------------------------------------------------
  \.                       '.'
--------------------------------------------------------------------------------
  (                        group and capture to :
--------------------------------------------------------------------------------
    [^.[:space:]]*           any character except: '.', whitespace
                             characters (like \s) (0 or more times
                             (matching the most amount possible))
--------------------------------------------------------------------------------
  )                        end of 
--------------------------------------------------------------------------------
  $                        before an optional \n, and the end of the
                           string