【问题标题】:REGEXP_SUBSTR function in Redshift does not return expected valueRedshift 中的 REGEXP_SUBSTR 函数不返回预期值
【发布时间】: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 吗?

标签: regex amazon-redshift


【解决方案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-]+)/?'
    • 啊,我担心正则表达式版本会有所不同。我不确定,也许尝试替换懒惰的“。*?”用'[\w.]+',恐怕我对Redshift不熟悉,也没有办法测试。
    • @JamesBaker 您的正则表达式不适用于 OP 代码。您需要包括使用示例。
    猜你喜欢
    • 1970-01-01
    • 2019-10-12
    • 2015-09-02
    • 1970-01-01
    • 2020-07-08
    • 2012-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多