Snowflake SQL 正则表达式 ~ 提取多个值

Snowflake SQL Regex ~ Extracting Multiple Vals

我正在尝试使用 Snowflakes regexp_substr()

来识别嵌套在字符串中的值

我要访问的值在引号中:

...
Type:
  a:
    - !<string>
     val: "A"
    - !<string>
     val: "B"
    - !<string>
     val: "C"
...

*这上面和下面有很多文字。

我想提取所有列的 A、B 和 C。但我不确定如何。我曾尝试使用 regexp_substr() 但无法隔离第一个值。 我试过:

REGEXP_SUBSTR(col, 'Type\W+(\w+)\W+\w.+\W+\w.+')

产生:

Type: a: - !<string> val: "A"

虽然这给出了带有 "A" 的字符串的第一部分,但我只想要一种单独访问 "A"、"B" 和 "C" 的方法。

这个 select 语句会给你你想要的......有点。您应该注意到它会查找 "val" 的特定出现,然后为您提供下一个单词字符。

据我所知,REGEX 的计算结果是表达式的第一次出现,所以一旦找到模式,它就完成了。您可能想查看 Snowflake JavaScript 存储过程,看看您是否可以采用下面的示例并进行迭代,增加适当的值以产生预期的输出。

SELECT REGEXP_SUBSTR('Type: a:- !<string>val: "A" - !<string> val: "B" - !<string> val: "C"','val\W+(\w+)', 1, 1, 'e', 1) as A,
       REGEXP_SUBSTR('Type: a:- !<string>val: "A" - !<string> val: "B" - !<string> val: "C"','val\W+(\w+)', 1, 2, 'e', 1) as B,
       REGEXP_SUBSTR('Type: a:- !<string>val: "A" - !<string> val: "B" - !<string> val: "C"','val\W+(\w+)', 1, 3, 'e', 1) as C;

您必须分两个阶段提取值;

  1. 提取文档的以下部分类型:a:包含所有 val: "data".
  2. "data"提取为数组或使用REGEXP_SUBSTR()+索引n提取第n元素
SELECT
  'Type:\s+\w+:((\s+- !<string>\s+val:\s+"[^"]")+)' type_section_rx
  REGEXP_SUBSTR(col, type_section_rx, 1, 1, 'i', 1) vals,
  PARSE_JSON('[0' || REPLACE(vals, REGEXP_SUBSTR(vals, '[^"]+'), ', ') || ']') raw_array,
  ARRAY_SLICE(raw_array, 1, ARRAY_SIZE(raw_array)) val_array,
  val_array[1] B
FROM INPUT_STRING

结果是一个数组,您可以在其中访问具有索引 [0] 等的第一个值。
第一个正则表达式可以缩短为 "least effort" 'Type:\s+\w+:(([^"]+"[^"]+")+)'.

另一个角度 -- 在 UDF 中使用 javascript 正则表达式功能。

例如:

create or replace function my_regexp(S text)
  returns array
  language javascript
as
$$
  const re = /(\w+)/g
  return [...S.match(re)]
$$
;

这样调用:

set S = '
Type:
  a:
    - !<string>
     val: "A"
    - !<string>
     val: "B"
    - !<string>
     val: "C"
';

select my_regexp($S);

产量:

[ "Type", "a", "string", "val", "A", "string", "val", "B", "string", "val", "C" ]

实现完整的正则表达式需要多做一些工作,但如您所见,这绕过了单值限制。

就是说,如果性能是您的首要任务,我希望 Snowflake 本机正则表达式支持表现出色,即使您多次指定正则表达式,但我还没有对此进行测试。