regex 如何在Snowflake中返回所有正则表达式匹配组?

cyvaqqii  于 2023-05-30  发布在  其他
关注(0)|答案(2)|浏览(178)

我想把一个字符串拆分成不同的部分,但是拆分比SPLIT() function所能处理的要复杂得多(使用一个简单的分隔符)。
有没有办法使用正则表达式在一次调用中返回所有的匹配组?

下面的例子过于简单,以保持问题的简洁。真实的的字符串和模式要复杂得多。

例如,我希望下面的例子返回["abc", "!@#", "123"]

SELECT REGEXP_SUBSTR('abc-!@#_123', '^(abc)-(!@#)_(123)$', 1, 1, 'ie', ALL);

但是,它必须在多个调用中完成(每个捕获组一个),当有很多组时,这变得很麻烦:

SELECT
  REGEXP_SUBSTR('abc-!@#_123', '^(abc)-(!@#)_(123)$', 1, 1, 'ie', 1),
  REGEXP_SUBSTR('abc-!@#_123', '^(abc)-(!@#)_(123)$', 1, 1, 'ie', 2),
  REGEXP_SUBSTR('abc-!@#_123', '^(abc)-(!@#)_(123)$', 1, 1, 'ie', 3);

然而,当存在具有多个匹配的组时,事情变得更加棘手(即当匹配组的总数是动态的时)。在下面的示例中,第三个匹配返回456而不是123

SELECT REGEXP_SUBSTR('abc-!@#_123_456', '^(abc)-(!@#)(_\\d+)+$', 1, 1, 'ie', 3);

我在想UDF可能是唯一的办法?

osh3o9ms

osh3o9ms1#

正如Tim提到的,你可以使用REGEXP_SUBSTR_ALL。在这种情况下,您需要删除锚点,然后搜索类似part\d+或更具体的内容。

SELECT REGEXP_EXTRACT_ALL('part1 part2 part3 part4', 'part\\d+', 1, 1, 'i');

(Note \d的转义也是如此。
另外,如果需要一个包含所有可能匹配项的数组,难道不能使用交替而不是所有捕获组吗?例如:

waxmsbnn

waxmsbnn2#

您可以使用REGEXP_SUBSTR_ALL来查找所有匹配项:

SELECT REGEXP_SUBSTR_ALL('a1_a2a3_a4A5a6', 'part[[:digit:]]+') AS matches
FROM yourTable

上面的语句将返回一个包含所有匹配项的数组。要从上面的数组中访问某个元素/匹配,我们可以使用GET()

SELECT GET(REGEXP_SUBSTR_ALL('a1_a2a3_a4A5a6', 'part[[:digit:]]+'), 1) AS second_match
FROM yourTable

上面的代码返回第二个匹配。

相关问题