正则表达式字符串,具有2个以上不同的数字和Snowflake语法中的一些可选字符 问题注释示例

我想检查我的一个表中的特定列是否满足以下条件:

  • 字符串必须至少包含三个字符

  • 字符串必须包含至少两个不同数字[例如123可以工作,但111不能工作]

  • 字符串中允许使用的字符:

    • 数字(0-9)
    • 大写字母
    • 小写字母
    • 下划线(_)]
    • 破折号(-)

我在Regex上有一些经验,但是对snowflake的语法有疑问。每当我尝试使用'?'正则表达式字符(将某些内容标记为可选)我收到错误消息。有人可以帮助我了解解决方法并提供解决方案吗?

到目前为止我所拥有的:

SELECT string,LENGTH(string) AS length 
    FROM tbl 
        WHERE REGEXP_LIKE(string,'^[0-9]+{3,}[-+]?[A-Z]?[a-z]?$')
    ORDER BY length;

谢谢!

liuyang0120 回答:正则表达式字符串,具有2个以上不同的数字和Snowflake语法中的一些可选字符 问题注释示例

您的正则表达式看起来有些混乱和无效,而且看起来也不能完全满足您的需求。我将这个表达式读为字符串:

  1. 必须以一位或多位数字开头,至少3次或多次
    • 让我感到困惑的部分是“ +”是一个量词,无法用{3,}进行量化,但是以某种方式不会对我产生错误
  2. 可选地后跟破折号或加号
  3. 后跟一个大写字符零或一遍(根据需要返回)
  4. 其后以零或一小写字符结尾,并以小写字符结尾(根据需要提供)

问题

您说您的字符串必须包含3个字符和至少2个不同的数字,数字是字符,但是我不确定您是不是指3个字母...

  • 您是否认为数字是字符?
  • 字符顺序重要吗?
  • 能否提供您收到的错误示例?

注释

检查与第二个数字不同的第二个数字涉及具有反向引用的超前查找的概念。 Snowflake不支持反向引用。

与正则表达式进行模式匹配有关的一件事是顺序会有所不同。如果顺序对您而言不重要,那么您将有多种模式可以匹配。

示例

下面是如何分别测试需求的每个部分。我提供了一些regexp_substr函数,以演示提取如何工作以检查是否再次存在。

取消注释WHERE子句以查看已过滤的数据集。过滤器被写为表达式,因此您可以删除任何/所有regexp_ *列。

select randstr(36,random(123)) as r_string,length(r_string) AS length,regexp_like(r_string,'^[0-9]+{3,}[-+]?[A-Z]?[a-z]?$') as reg,'.*[A-Za-z]{3,}.*') as has_3_consecutive_letters,'.*\\d+.*\\d+.*') as has_2_digits,regexp_substr(r_string,'(\\d)',1,1) as first_digit,2) as second_digit,first_digit <> second_digit as digits_1st_not_equal_2nd,not(regexp_instr(r_string,1),2)) as first_digit_does_not_appear_again,has_3_consecutive_letters and has_2_digits and first_digit_does_not_appear_again as test
from table(generator(rowcount => 10))
//where regexp_like(r_string,}.*') // has_3_consecutive_letters
//    and regexp_like(r_string,'.*\\d+.*\\d+.*') // has_2_digits
//    and not(regexp_instr(r_string,2)) // first_digit_does_not_appear_again
;
,

假设数字必须是连续的,则可以使用javascript UDF在具有最大不同数字位数的字符串中查找数字:

create or replace function f(S text)
returns float
language javascript
returns null on null input 
as
$$
    const m = S.match(/\d+/g)
    if (!m) return 0
    const lengths = m.map(m=> [...new Set (m.split(''))].length)
    const max_length = lengths.reduce((a,b) => Math.max(a,b)) 
    return max_length 
$$
;

我相信,结合WHERE条款,这可以满足您的需求

select column1,f(column1) max_length 
from t
where max_length>1 and length(column1)>2 and column1 rlike '[\\w\\d-]+';

屈服:

COLUMN1                 | MAX_LENGTH
------------------------+-----------
abc123def567ghi1111_123 |          3
123                     |          3
111222                  |          2

假设此输入:

create or replace table t as
select * from values ('abc123def567ghi1111_123'),('xyz111asdf'),('123'),('111222'),('abc 111111111 abc'),('12'),('asdf'),('123 456'),(null);

如果数字不必是连续的(即计算字符串中的不同数字),则该功能甚至更简单。然后核心逻辑变为:

    const m = S.match(/\d/g)
    if (!m) return 0
    const length = [...new Set (m)].length
    return length

希望有帮助!

本文链接:https://www.f2er.com/2898369.html

大家都在问