简体   繁体   中英

Postgresql regex match string with substring

I have a string foo,bar what i want to do is to form a query matching both of them (can have gap between them)

for example it should be matching against entries like

aaa,bbbb,foo,zzz,bar
bar,ccc,ddddd,foo,iiiii

but not

aaa,eeeee,foo,rrrrrr,hhhhhh
ooooo,ii,sssss,bar,xxxx

the column that i'm trying to matching against is of type text

i tried doing it like this

select * from string_entries where str similar to '%(?=.*foo)(?=.*bar)%';

but i'm getting this error

ERROR:  invalid regular expression: quantifier operand invalid
SQL state: 2201B

Assuming these values must appear as full comma-separated entries, you can use

where str ~ '^(?=.*(?:,|^)foo(?:,|$))(?=.*(?:,|^)bar(?:,|$))'

Here, it will match strings that contain foo and bar in any order using the ~ (regex matching) operator. Details :

  • ^ - start of string
  • (?=.*(?:,|^)foo(?:,|$)) - immediately on the right, there should be any zero or more chars, as many as possible, and then a foo string (either at the start of string or right after a comma and followed with a comma or end of string position)
  • (?=.*(?:,|^)bar(?:,|$)) - immediately on the right, there should be any zero or more chars, as many as possible, and then a bar string (either at the start of string or right after a comma and followed with a comma or end of string position)

Assuming these values must appear as whole words you can replace the non-capturing groups with \\y word boundaries and use

where str ~ '^(?=.*\yfoo\y)(?=.*\ybar\y)'

See the online DB fiddle :

CREATE TABLE string_entries
    (str character varying)
;

INSERT INTO string_entries
    (str)
VALUES
    ('aaa,bbbb,foo,zzz,bar'),
    ('bar,ccc,ddddd,foo,iiiii'),
    ('aaa,eeeee,foo,rrrrrr,hhhhhh'),
    ('ooooo,ii,sssss,bar,xxxx')
;

select str from string_entries where str ~ '^(?=.*(?:,|^)foo(?:,|$))(?=.*(?:,|^)bar(?:,|$))';

在此处输入图片说明

I am inclined to not do this with a regex comparison, but convert the string into an array:

select *
from string_entries 
where string_to_array(str, ',') @> array['foo', 'bar']

This will only work if you need equality comparison. If you wanted to also match using eg foo% rather than foo then this would work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM