使用Postgres正则表达式搜索返回匹配的子字符串

时间:2013-11-05 16:54:45

标签: sql regex postgresql

我试图从Postgres的varchar字段中提取一些值。 * product_name *字段可能包含类似“Big Bag 24-0-3 Twenty Gallons”或“Small Bag 0-14-40”的内容,产品代码为# - # - #。产品代码中的数字可以是0,也可以是一个或两个数字,但总会有三个数字用两个破折号分隔。

我已经正确地返回了匹配的产品,但是现在我需要将每个数字放在一个单独的字段中,所以我真的很感激一个脑子比我帮助输出子字符串更大的人!

此正则表达式匹配会返回正确的产品:

select * from products where product_name LIKE '%_-_-_%'

我试图使用子字符串返回产品代码,但它正在切断具有两位数的第三个数字的产品(即'Big Bag 24-0-32 Foo'将返回'24 -0-3' )

select trim(substring(name from '%#"__-_-_#"%' for '#')),* 
from products where name LIKE '%_-_-_%'

实际上,整个数字并没有给我带来太多好处 - 我真的需要在一个单独的子串中提取三个数字中的每一个。

2 个答案:

答案 0 :(得分:7)

一种选择是使用regexp_matches来提取代码:

  

regexp_matches(string text, pattern text [, flags text])
  返回通过将POSIX正则表达式与字符串匹配而得到的所有捕获的子字符串。

然后regexp_split_to_array

  

regexp_split_to_array(string text, pattern text [, flags text ])
  使用POSIX正则表达式作为分隔符拆分字符串。

将代码分成数字。例如:

=> select regexp_split_to_array((regexp_matches('Big Bag 24-0-3 Twenty Gallons', E'(\\d+-\\d+-\\d+)'))[1], '-');
 regexp_split_to_array 
-----------------------
 {24,0,3}
(1 row)

{24,0,3}是一个三元素数组,包含您感兴趣的三个数字(作为字符串)。如果三行表比数组更容易使用,还有regexp_split_to_table

=> select regexp_split_to_table((regexp_matches('Big Bag 24-0-3 Twenty Gallons', E'(\\d+-\\d+-\\d+)'))[1], '-');
 regexp_split_to_table 
-----------------------
 24
 0
 3
(3 rows)

答案 1 :(得分:1)

这不像你正在寻找的正则表达式,但它可能会让你更接近:

Select substring( arr[ 1 ] from '[0-9][0-9]*' ) as first,
    arr[ 2 ] as second,
    substring( arr[ 3 ] from '[0-9][0-9]*' ) as third
FROM
(
Select string_to_array( d1, '-' ) as arr
from
(
SELECT * FROM ( VALUES
( 1, 'Big Bag 24-0-3 Twenty Gallons' ),
( 2, 'Small Bag 0-14-40' ),
( 3, 'Big Bag 24-0-32 Foo' ),
( 4, 'Other Bag 4-4-24' )
) AS products( id, d1 )
) AS values_table
) AS get_array

在一次通过中可能有一种更好的方法可以做到这一点并且没有所有的块AS别名但是这里是细分:

  • VALUES表提供测试数据 - d1是要获取的数据。
  • 这是由string_to_array()中的-进行解析,以获取包含Big Bag 2403 Twenty Gallons(自动键入的)字符串的数组;
  • 外部选择仅通过从第一个和最后一个数组元素中选取数字来转换数组值。

可以将这种工作放入函数中以获取每个数字但是应该进行NULL测试等。