带有连字符的Oracle正则表达式在Windows上与在Unix上没有相同的结果

时间:2014-10-14 14:43:12

标签: regex oracle sqlplus

我使用正则表达式进行以下查询:

select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG 
from dual;

Windows 计算机上通过SQL * Plus执行时,它会返回以下内容:

SQL>  select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;

REG
------------
TEST 3304 V2

SunOS 计算机上,我得到了不同的结果:

SQL>  select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;

REG
------------
TEST      V

这些查询是针对同一个Oracle服务器运行的。是否有任何原因导致产出差异?

Windows上的SQL * Plus版本:

SQL*Plus: Release 11.2.0.1.0 Production on Mar. Oct. 14 15:36:35 2014

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

Unix上的SQL * Plus版本:

SQL*Plus: Release 11.2.0.2.0 Production on Tue Oct 14 16:01:26 2014

Copyright (c) 1982, 2010, Oracle.  All rights reserved.


Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

1 个答案:

答案 0 :(得分:4)

正如Avinash Raj在评论中所说,正则表达式中的连字符被解释为范围。该行为似乎取决于两个客户端使用的排序算法,基于NLS_LANG环境变量,它会影响NLS_SORT值。

使用NLS_LANG=ENGLISH_UNITED KINGDOM.WE8ISO8859P1

SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;

REG
------------
TEST      V

SQL> select value from nls_session_parameters where parameter = 'NLS_SORT';

VALUE
----------
BINARY

当你的个人资料显示你在摩洛哥,NLS_LANG="ARABIC_MOROCCO.AR8MSWIN1256"时出去了:

SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;

REG
------------
TEST 3304 V2

SQL> select value from nls_session_parameters where parameter = 'NLS_SORT';

VALUE
----------
ARABIC

原因是模式片段+-=被视为涵盖从+=的所有字符的范围。在ISO8859-1和Windows 1252 character set中,字符43到61,并且所有数字都在该范围内 - 例如零是48 - 在该范围内,因此正则表达式替换它们。在Windows 1256 character set中也是如此。 (以及基于ASCII的任何内容)。

但是你的NLS_LANG也隐式改变了排序顺序,它从BINARY切换到ARABIC排序,改变了行为。你可以在一个会话中看到;与NLS_LANG=ENGLISH_UNITED KINGDOM.WE8ISO8859P1

SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;

REG
------------
TEST      V

SQL> alter session set NLS_SORT=ARABIC;

Session altered.

SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;

REG
------------
TEST 3304 V2

您也可以通过稍微修改范围来判断它是一个范围问题;将+-=更改为+-3,不包括更高的数字,但保留其他所有内容:

SQL> alter session set NLS_SORT=BINARY;

Session altered.

SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-3{}|;.:<>?,./]', ' ') as REG from dual;

REG
------------
TEST    4 V

Read more about linguistic sorting

依赖于NLS设置总是有风险的,所以最好通过改变模式以在开头或结尾处使用连字符来完全避免范围问题,从而阻止它被视为一个范围;再次像阿维纳什拉吉所说的那样。