查找所有出现的正则表达式作为数组

find all occurrences of a regex as an array

有以下字​​符串(这是一个 salesforce 查询,但不重要):

IF(OR(CONTAINS(EmailDomain,"yahoo"),CONTAINS(EmailDomain,"gmail"),
CONTAINS("protonmail.com,att.net,chpmail.com,smail.com",EmailDomain)),
"Free Mail","Business Email")

我想得到一个包含所有子字符串的数组,这些子字符串被封装在双引号之间,如下所示:

['yahoo',
'gmail',
'protonmail.com,att.net,chpmail.com,smail.com',
'Free Mail',
'Business Email']

在python我做:

re.findall(r'"(.+?)"', <my string>)

但是有没有办法在 Snowflake 中复制它?

我试过了

SELECT 
REGEXP_SUBSTR('IF(OR(CONTAINS(EmailDomain,"yahoo"),CONTAINS(EmailDomain,"gmail"),
CONTAINS("protonmail.com,att.net,chpmail.com,smail.com",EmailDomain)),
"Free Mail","Business Email")', '"(.+?)"') as emails;

但我明白了:

"yahoo"),CONTAINS(EmailDomain,"gmail"

您可以使用

select split(trim(regexp_replace(regexp_replace(col, '"([^"]+)"|.', '\1|'),'\|+','|'), '|'), '|');

详情:

  • regexp_replace(col, '"([^"]+)"|.', '\1|') - 查找最接近的双引号之间的任何字符串,同时将引号内的部分捕获到组 1 中,或匹配任何单个字符并将每个匹配项替换为组 1 内容 + | 字符 (参见 the regex demo)
  • regexp_replace(...,'\|+','|') - 这会将所有连续的管道符号缩小为单个出现的 | 字符(参见 this regex demo
  • trim(..., '|') - 删除字符串两端的 | 个字符
  • split(..., '|') - 用 | 字符拆分字符串。

Wiktor 的回答很有效。我正在为任何需要这样做的人添加一个替代答案,他们引用的字符串可能包含竖线 | 字符。对包含管道的字符串使用替换方法会将字符串拆分为多个数组成员。这里有一种方法(不是唯一的方法)可以在引用的字符串可能包含管道字符的情况下工作:

set col = $$IF(OR(CONTAINS(EmailDomain,"yahoo"),CONTAINS(EmailDomain,"gmail"),CONTAINS("protonmail.com,att.net,chpmail.com,smail.com",EmailDomain)),"Free Mail","Business Email | Other")$$;

create or replace function GET_QUOTED_STRINGS("s" string)
returns array
language javascript
strict immutable
as
$$

var re = /(["'])(?:\.|[^\])*?/g;
var m;
var out = [];

do {
    m = re.exec(s);
    if (m) {
        out.push(m[0].replace(/['"]+/g, ''));
    }
} while (m);

return out;

$$;

select get_quoted_strings($col);