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]*)$
正在寻找:
- 一个点字符
\.
;然后
- 零个或多个不是点
.
或斜线 \
或 n
或斜线 \
或 [=19= 的字符];然后
- 字符串结尾。
问题是你的字符串有一个 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
我在寻找解决方案时遇到问题
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]*)$
正在寻找:
- 一个点字符
\.
;然后 - 零个或多个不是点
.
或斜线\
或n
或斜线\
或 [=19= 的字符];然后 - 字符串结尾。
问题是你的字符串有一个 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