查找所有出现的正则表达式作为数组
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);
有以下字符串(这是一个 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);