2012-02-10 24 views
0

我有一个应用程序,我一直在努力,今晚发现一个令人不安的区别 - 我想我会在这里记录下来,看看是否有人可以复制它和/或解释它。查询是编造的,但说明了问题:PostgreSQL正则表达式匹配版本不同

select 
    '123' ~ '^\d+$' as result_1, 
    '123' ~ '^[0-9]+$' as result_2 

我有一个PostgreSQL 9.1在Windows 7上运行,当我运行此查询,我得到:

T,T

然而,当我在Ubuntu的10.04 PostgreSQL运行V9.0查询我得到:

F,T

所以,看起来PostgreSQL在处理“\ d”时在v9.0和v9.1之间改变了,或者它与Windows和Ubuntu之间安装的库之间的差异有些不同。无论哪种方式,我认为民间人士应该意识到,你的支票限制等可能不会在两者之间表现相同(我肯定没有)。

注意:不幸的是,我不能轻松访问运行9.0的Windows 7盒子,或者我也会在那里测试它。

任何人都可以解释这一点吗?如果众所周知,请原谅我。我在Google上搜索时没有看到答案。很显然,安全的做法是仅使用[0-9],因为它可以在两个位置都可以使用。但是,我想再次想知道为什么会发生这种情况。

回答

2

你有一个逃跑的问题。从fine 9.1 manual on string quoting

如果配置参数standard_conforming_strings是关闭的,那么PostgreSQL的识别反斜杠常规和逃避字符串常量逃脱。但是,从PostgreSQL 9.1开始,默认是打开的,这意味着反斜杠转义仅在转义字符串常量中被识别。

因此,9.1看到'\d'与C相同,所以它看起来像'd'。 9.1你想要逃避你反斜线和使用E''“越狱”串号来获取过去standard_conforming_strings

select 
    '123' ~ E'^\\d+$' as result_1, 
    '123' ~ '^[0-9]+$' as result_2 

或者你可以尝试dollar quoting

select 
    '123' ~ $re$^\d+$$re$ as result_1, 
    '123' ~ '^[0-9]+$' as result_2 

但是这是相当丑陋,难使用正则表达式(特别是使用$来锚定结尾的正则表达式)进行读取。

另一种选择是使用的POSIX character class,而不是\d

select 
    '123' ~ '^[[:digit:]]+$' as result_1, 
    '123' ~ '^[0-9]+$' as result_2 

你应该已经看到警告有关在早期版本的'\d',那么请你的日志这样的事情:

WARNING: nonstandard use of escape in a string literal 
LINE 1: select '\d'; 
      ^
HINT: Use the escape string syntax for escapes, e.g., E'\r\n'. 
+0

谢谢!很好的回答和解释。我已经测试了'123'〜E'^ \\ d + $'作为result_1,可以在windows和linux以及9.0和9.1上运行 – 2012-02-10 14:58:07