具有 2 个以上不同数字和 Snowflake 语法中的一些可选字符的正则表达式字符串
Regex string with 2+ different numbers and some optional characters in Snowflake syntax
我想检查我的一个表中的特定列是否满足以下条件:
字符串必须至少包含三个字符
字符串必须至少包含两个不同的数字[例如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;
谢谢!
假设数字需要连续,您可以使用 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-clause,这就是你想要的,我相信:
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
希望对您有所帮助!
你的正则表达式看起来有点混乱和无效,而且它看起来也不太符合你的需要。我将这个表达式读作一个字符串:
- 必须以一位或多位数字开头,至少3次或更多次
- 令我困惑的部分是“+”是一个量词,它不能用 {3,} 量化,但不知何故不会为我产生错误
- 可以选择后跟破折号或加号
- 后跟一个大写字符零次或一次(根据需要返回)
- 后跟并以小写字符结尾零次或一次(根据需要返回)
问题
你说你的字符串必须包含 3 个字符和至少 2 个不同的数字,数字是字符,但我不确定你的意思是不是 3 个字母...
- 您认为数字是字符吗?
- 字符的顺序重要吗?
- 能否举例说明您收到的错误?
备注
检查与第一个数字不同的第二个数字涉及使用反向引用的先行概念。 Snowflake 不支持反向引用。
关于使用正则表达式进行模式匹配的一个问题是顺序会有所不同。如果顺序对您不重要,那么您将有多种模式可以匹配。
例子
下面是您可以单独测试需求的每个部分的方法。我已经包括了一些 regexp_substr 函数来展示提取如何工作以检查是否再次存在。
取消注释 WHERE 子句以查看过滤后的数据集。过滤器被写成表达式,因此您可以删除 regexp_* 列的 any/all。
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
,regexp_like(r_string,'.*[A-Za-z]{3,}.*') as has_3_consecutive_letters
,regexp_like(r_string,'.*\d+.*\d+.*') as has_2_digits
,regexp_substr(r_string,'(\d)',1,1) as first_digit
,regexp_substr(r_string,'(\d)',1,2) as second_digit
,first_digit <> second_digit as digits_1st_not_equal_2nd
,not(regexp_instr(r_string,regexp_substr(r_string,'(\d)',1,1),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,'.*[A-Za-z]{3,}.*') // has_3_consecutive_letters
// and regexp_like(r_string,'.*\d+.*\d+.*') // has_2_digits
// and not(regexp_instr(r_string,regexp_substr(r_string,'(\d)',1,1),1,2)) // first_digit_does_not_appear_again
;
我想检查我的一个表中的特定列是否满足以下条件:
字符串必须至少包含三个字符
字符串必须至少包含两个不同的数字[例如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;
谢谢!
假设数字需要连续,您可以使用 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-clause,这就是你想要的,我相信:
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
希望对您有所帮助!
你的正则表达式看起来有点混乱和无效,而且它看起来也不太符合你的需要。我将这个表达式读作一个字符串:
- 必须以一位或多位数字开头,至少3次或更多次
- 令我困惑的部分是“+”是一个量词,它不能用 {3,} 量化,但不知何故不会为我产生错误
- 可以选择后跟破折号或加号
- 后跟一个大写字符零次或一次(根据需要返回)
- 后跟并以小写字符结尾零次或一次(根据需要返回)
问题
你说你的字符串必须包含 3 个字符和至少 2 个不同的数字,数字是字符,但我不确定你的意思是不是 3 个字母...
- 您认为数字是字符吗?
- 字符的顺序重要吗?
- 能否举例说明您收到的错误?
备注
检查与第一个数字不同的第二个数字涉及使用反向引用的先行概念。 Snowflake 不支持反向引用。
关于使用正则表达式进行模式匹配的一个问题是顺序会有所不同。如果顺序对您不重要,那么您将有多种模式可以匹配。
例子
下面是您可以单独测试需求的每个部分的方法。我已经包括了一些 regexp_substr 函数来展示提取如何工作以检查是否再次存在。
取消注释 WHERE 子句以查看过滤后的数据集。过滤器被写成表达式,因此您可以删除 regexp_* 列的 any/all。
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
,regexp_like(r_string,'.*[A-Za-z]{3,}.*') as has_3_consecutive_letters
,regexp_like(r_string,'.*\d+.*\d+.*') as has_2_digits
,regexp_substr(r_string,'(\d)',1,1) as first_digit
,regexp_substr(r_string,'(\d)',1,2) as second_digit
,first_digit <> second_digit as digits_1st_not_equal_2nd
,not(regexp_instr(r_string,regexp_substr(r_string,'(\d)',1,1),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,'.*[A-Za-z]{3,}.*') // has_3_consecutive_letters
// and regexp_like(r_string,'.*\d+.*\d+.*') // has_2_digits
// and not(regexp_instr(r_string,regexp_substr(r_string,'(\d)',1,1),1,2)) // first_digit_does_not_appear_again
;