Postgresql regexp_matches语法无法按预期工作

时间:2018-01-05 08:56:18

标签: regex postgresql

我使用Postgres regexp_matches 函数来提取数字。

我使用的正则表达式是

4([\s\-\/\.]*?0){3}([\s\-\/\.]*?[12]){1}([\s\-\/\.]*?\d){4}

如果我使用像https://regexr.com/这样的工具来验证它是否有效并且我应用了以下测试集

4-0001-1234
5-2342-2344
499999999
4-0001-1234 4.0001.12344  4-0-0-0-1-1234

我得到了预期的提取结果:

4-0001-1234
4-0001-1234
4.0001.1234
4-0-0-0-1-1234

但是,如果我在Postgresql中使用相同的表达式,它确实可以正常工作:

SELECT unnest(regexp_matches('4-0001-1234', '4([\s\-\/\.]*?0){3}([\s\-\/\.]*?[12]){1}([\s\-\/\.]*?\d){4}', 'g'));

结果:

0
1
4

我怀疑的是,它与贪婪有关,和/或 {3} 等量词没有以正确的方式应用。或者它使用正则表达式的Posix标准,它似乎与Java语法略有不同。

为什么它不起作用以及如何解决它的任何建议?

1 个答案:

答案 0 :(得分:2)

regexp_matches(string text, pattern text [, flags text])函数返回捕获的值:

  

返回通过将POSIX正则表达式与字符串匹配而产生的所有捕获的子字符串。

您可以使用非捕获组修复表达式:

SELECT unnest(regexp_matches('4-0001-1234 4.0001.12344  4-0-0-0-1-1234', '4(?:[\s/.-]*0){3}(?:[\s/.-]*[12])(?:[\s/.-]*\d){4}', 'g'));

请参阅online demo

enter image description here

顺便说一下,当它位于括号表达式的开头/结尾时,你不需要转义-,并且不需要在那里/.都没有。我还建议在支持限制量词的任何正则表达式中将{1}删除为a = a{1}