正则表达式无法匹配数字和短划线与字母(或空格和字母)

时间:2013-12-02 20:55:42

标签: regex postgresql

tester这有效......但不在PostgreSQL中。

我的数据是这样的 - 通常是一系列字母,后跟2个数字和一个可能的' - '或'空格',后面只有一个字母。我试图用我的正则表达式隔离2个数字和可能的' - '或'空格'和ONE字母:

例如:

AJ 50-R Busboys ## should return 50-R
APPLES 30 F ## should return 30 F 
FOOBAR 30 Apple ## should return 30

我试过的正则表达式(曾在测试人员中工作,但在PostgreSQL中没有):

substring(REF from '([0-9]+)-?([:space:])?([A-Za-z])?') 

&安培;

substring(REF from '([0-9]+)-?([A-Za-z])?') 

到目前为止,一切都在测试人员中测试...但不是PostgreSQL。我只是不断获得数字回报 - 并且在它之后没有。

我现在得到的(前):

AJ 50-R Busboys ## returns as "50" NOT as "50-R"

3 个答案:

答案 0 :(得分:2)

您正在寻找:substring(REF from '([0-9]+(-| )([A-Za-z]\y)?)')

SQLFiddle。你的主要问题是substring返回第一个或最外面的匹配组(即,()包围的模式),这就是为什么你的'50 -R'得到50的原因。如果你用()包围整个模式,这将给你'50 -R'。但是,即使考虑到这个问题,你所拥有的模式也无法返回你想要的其他字符串,所以我不得不修改整个正则表达式。

答案 1 :(得分:2)

这符合您的描述和示例 您的描述有点含糊不清。前导字母后跟空格,然后是示例中的两位数字,而不是您的描述。

SELECT t, substring(t, '^[[:alpha:] ]+(\d\d(:?[\s-]?[[:alpha:]]\M)?)')
FROM  (
   VALUES
     ('AJ 50-R Busboys')       -- should return: 50-R
    ,('APPLES 30 F')           -- should return: 30 F 
    ,('FOOBAR 30 Apple')       -- should return: 30
    ,('FOOBAR 30x Apple')      -- should return: 30x
    ,('sadfgag30 D 66 X foo')  -- should return: 30 D - not: 66 X
   ) r(t);

->SQLfiddle

解释

^ ..字符串的开头(最后一行可能会失败而不会锚定到start和全局标志'g')。另外:更快 [[:alpha:] ]+ ..一个或多个字母或空格(如示例中所示) ( ..捕捉括号
\d\d ..两位数
(:? ..非捕获括号
[\s-]? .. '-' or 'white space'(字符类),0或1次
[[:alpha:]] .. 1个字母
\M ..后跟单词结尾(也可以是字符串结尾)
)? ..非捕获括号中的模式0或1次

根据当前区域设置由character class alpha定义的字母!穷人的替代[a-zA-Z]仅适用于基本的ASCII字母,并且不再适用于其他任何内容。考虑一下这个简单的演示:

SELECT  substring('oö','[[:alpha:]]*')
       ,substring('oö','[a-zA-Z]*');

More about character classes in Postgres regular expressions in the manual.

答案 2 :(得分:1)

这是因为括号。

我在文档中随处可见,并在this page找到了一个有趣的句子:

  

[...]如果模式包含任何括号,则返回与第一个带括号的子表达式(左括号首先出现的那个)匹配的文本部分。

我拿了你的第一个表达:

([0-9]+)-?([:space:])?([A-Za-z])?

并将其包装在括号中:

(([0-9]+)-?([:space:])?([A-Za-z])?)

它工作正常(见SQLFiddle)。

更新

另外,因为您正在寻找-或空格,所以您可以将中间表达式重写为[-|\s]?(感谢Matthew指出这一点),这会导致以下可能正则表达式:

(([0-9]+)[-|\s]?([A-Za-z])?)

SQLFiddle

更新2:

虽然我的回答提供了解释为什么结果表示您的表达式的部分匹配,但我上面提到的表达式未能通过您的第三个测试用例。

您应该使用Matthew在his answer中提供的正则表达式。