简体   繁体   English

Postgresql正则表达式匹配字符串与子字符串

[英]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)我有一个字符串foo,bar我想要做的是形成一个匹配它们的查询(它们之间可以有间隙)

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我试图匹配的列是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.在这里,它将使用~ (正则表达式匹配)运算符以任何顺序匹配包含foobar字符串。 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) (?=.*(?:,|^)foo(?:,|$)) - 在右边,应该有零个或多个字符,尽可能多,然后是一个foo字符串(或者在字符串的开头或逗号后紧跟逗号或字符串结尾位置)
  • (?=.*(?:,|^)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) (?=.*(?:,|^)bar(?:,|$)) - 紧靠右侧,应该有零个或多个字符,尽可能多,然后是bar字符串(或者在字符串的开头或逗号后紧跟逗号或字符串结尾位置)

Assuming these values must appear as whole words you can replace the non-capturing groups with \\y word boundaries and use假设这些值必须作为整个单词出现,您可以用\\y单词边界替换非捕获组并使用

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.如果您还想使用例如foo%而不是foo进行匹配,那么这将起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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