在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"
答案 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);
^
..字符串的开头(最后一行可能会失败而不会锚定到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])?)
更新2:
虽然我的回答提供了解释为什么结果表示您的表达式的部分匹配,但我上面提到的表达式未能通过您的第三个测试用例。
您应该使用Matthew在his answer中提供的正则表达式。