Redshift 中的 REGEXP_SUBSTR 函数不返回预期值

Posted

技术标签:

【中文标题】Redshift 中的 REGEXP_SUBSTR 函数不返回预期值【英文标题】:REGEXP_SUBSTR function in Redshift does not return expected value 【发布时间】:2019-11-20 07:34:58 【问题描述】:

我有一个名为 URL 的列的表。我正在尝试使用 Redshift 中的REGEX_SUBSTR 函数提取 URL 的不同部分。

URL                                             Expected_output
------------                                 
www.abcd.com/first-name                      |   first-name
www.abcd.com/another-name/some-details/other |   another-name
www3.abcd.com/some-name/                     |   some-name
form.abcd.com/another-first-name             |   another-first-name

所以目的是提取域名后的第一个slug

我试过了SELECT REGEXP_SUBSTR('www.abcd.com/slug-name', '(www|www3|form)[.]abcd[.][^/]+/([^/#?]+)',1,2)

输出www.abcd.com/slug-name

【问题讨论】:

如果你使用REGEXP_SUBSTR('www.abcd.com/slug-name', '[^/]+',1,2)会怎样?还是只需要在特定上下文中匹配? 请提供有关您希望匹配发生的确切上下文的反馈,这很重要,因为此正则表达式引擎似乎不支持非捕获组。你需要检查(www|www3|form)吗? 是的,我需要检查这是一个以www|www3|form开头的有效网址 那么我认为你不能使用REGEXP_SUBSTR,因为它只能提取 first 捕获组的内容,其他的被忽略,因为它使用 POSIX 正则表达式标准,不支持非捕获组。您需要使用两步解决方案。 知道了。 2 步是指使用 UDF 吗? 【参考方案1】:

由于您需要在模式中进行多个分组,第一个分组定义了预期的匹配上下文(因此,您不需要提取第一组内容),并且REGEXP_SUBSTR 仅支持使用e 提取第一组修饰符,你必须回退到REGEXP_REPLACE

注意:REGEXP_REPLACE 删除匹配项,如果字符串没有匹配项,它将保持原样。 REGEXP_SUBSTR 将返回一个空白值。

所以,你可以考虑

REGEXP_REPLACE('www.abcd.com/slug-name', '^(www3?|form)\\.abcd\\.[^/]+/([^/#?]+).*', '$2')

或者,删除不匹配的条目文本(注意末尾添加的|.+):

REGEXP_REPLACE('www.abcd.com/slug-name', '^(www3?|form)\\.abcd\\.[^/]+/([^/#?]+).*|.+', '$2')

所以,^(www3?|form)\\.abcd\\.[^/]+/([^/#?]+).* 匹配

^ - 字符串开头 (www3?|form) - 第 1 组:www 和可选的 3 \.abcd\. - .abcd. 子字符串 [^/]+ - 除/ 之外的 1+ 个字符 / - 一个 / 字符 ([^/#?]+) - 第 2 组(通过​​替换模式中的 $2 反向引用引用):除 /#? 之外的 1 个或多个字符 .* - 尽可能多的任何 0+ 个字符

|.+ 表示“或任何 1+ 个字符”。也就是说,如果第一个替代项没有找到匹配项,则删除整个文本。

【讨论】:

【参考方案2】:

您可以忽略直到第一个正斜杠的任何内容,在第一个正斜杠之后捕获组,直到第二个(如果存在)。在捕获组中,您想要获取带有字符(可能不是大写)、连字符和下划线的任何内容。我发现 '\w-' 匹配下划线和连字符。

试试这个表达式:

^.*?\/([\w-]+)\/?.*

我在以下字符串上对此进行了测试:

www.abcd.com/first-name                     
www.abcd.com/another-name/some-details/other 
www3.abcd.com/some-name/                    
form.abcd.com/another-first-name
form.abcd.com/another_first-name
form.abcd.com/anotherfirst-name

我使用tool on Regex 101 给我这些匹配项:

Match 1
Full match  0-44    www.abcd.com/first-name                     
Group 1.    13-23   first-name
Match 2
Full match  45-90   www.abcd.com/another-name/some-details/other 
Group 1.    58-70   another-name
Match 3
Full match  91-135  www3.abcd.com/some-name/                    
Group 1.    105-114 some-name
Match 4
Full match  136-168 form.abcd.com/another-first-name
Group 1.    150-168 another-first-name
Match 5
Full match  169-201 form.abcd.com/another_first-name
Group 1.    183-201 another_first-name
Match 6
Full match  202-233 form.abcd.com/anotherfirst-name
Group 1.    216-233 anotherfirst-name

【讨论】:

Invalid preceding regular expression prior to repetition operator. The error occurred while parsing the regular expression fragment: '^.*?>>>HERE>>>/([w-]+)/?' 一些类似的错误***.com/questions/46495580/redshift-regexp-substr 啊,我担心正则表达式版本会有所不同。我不确定,也许尝试替换懒惰的“。*?”用'[\w.]+',恐怕我对Redshift不熟悉,也没有办法测试。 @JamesBaker 您的正则表达式不适用于 OP 代码。您需要包括使用示例。

以上是关于Redshift 中的 REGEXP_SUBSTR 函数不返回预期值的主要内容,如果未能解决你的问题,请参考以下文章

Redshift REGEXP_SUBSTR 函数的 Spark 替代方案

regexp_substr 提取字符串中的度量单位

HIVE SQL 中的 REGEXP_SUBSTR 等效项?

如何使 BigQuery 中的 REGEXP_SUBSTR() 函数匹配非贪婪?

REGEXP_SUBSTR - 如何“避免”字符串中的括号

oracle sql中的regexp_substr