【问题标题】:Finding nth occurrence of a pattern within a string in SQL (Presto)在 SQL (Presto) 中的字符串中查找模式的第 n 次出现
【发布时间】:2021-05-19 20:36:29
【问题描述】:

我正在使用函数 regexp_extract 在 Presto SQL 中编写查询

我有一个可能类似于以下示例的字符串:

'1A2B2C3D3E'
'1A1B2C2D3E'
'1A2B1C2D2E'

我要做的是找到例如 second 出现的 1[A-E]。

如果我尝试

regexp_extract(col, '(1[A-E])(1[A-E])', 2)

这将适用于第二个示例(第一个示例,因为它没有返回任何内容,因为没有第二次出现)。但是,这对于第三个示例将失败。它什么也不返回。我知道这是因为我的正则表达式正在搜索一个 1[A-E],直接 后面跟着另一个 1[A-E]。

然后我尝试了

regexp_extract(col, '(1[A-E])(.*)(1[A-E])', 3)

但这也不起作用。我不确定如何解释我可能有 1A1B2C 或 1A2B1C 来找到第二个 1。有什么帮助吗?

【问题讨论】:

  • 我不了解 Presto,但您的第二种模式看起来应该可以工作。唯一的问题是您应该使用惰性量词(即.*? 而不是.*)否则第 3 组将包含 last 出现,不一定是 second一。 “不起作用”到底是什么意思?你有任何结果吗?

标签: regex presto trino


【解决方案1】:

您的第二个模式在最新版本的 Trino (formerly known as Presto SQL) 中确实有效:

WITH t(col) AS (
  VALUES 
    '1A2B2C3D3E', 
    '1A1B2C2D3E',
    '1A2B1C2D2E')
SELECT regexp_extract(col, '(1[A-E])(.*)(1[A-E])', 3)
FROM t
 _col0
-------
 NULL
 1B
 1C
(3 rows)

正如其他人评论的那样,对于第一次匹配或 .*,您不需要捕获组,并且您应该使用惰性量词来避免 .* 急切匹配第一次和最后一次出现之间的所有字符:

WITH t(col) AS (
    VALUES 
        '1A2B2C3D3E', 
        '1A1B2C2D3E',
        '1A2B1C2D2E', 
        '1A2B1C2D1E') 
SELECT regexp_extract(col, '1[A-E].*?(1[A-E])', 1)
FROM t
 _col0
-------
 NULL
 1B
 1C
 1C
(4 rows)

【讨论】:

    【解决方案2】:

    您不需要第二个捕获组 (.*) 将 2 个捕获组保留在结果中,您可以选择匹配其间允许的字符。

    根据我在this page 上阅读的内容,您还可以考虑使用regexp_extract_all 来获取所有匹配项,因为regexp_extract 返回第一个匹配项。

    由于示例数据由一个数字后跟一个字符 A-E 组成,因此您可以从字符类中排除匹配 1 以防止过度匹配和回溯。

    (1[A-E])[02-9A-E]*(1[A-E])
    

    Regex demo

    如果使用单个捕获组获取第二个值也可以,可以使用

    1[A-E][02-9A-E]*(1[A-E])
    

    Regex demo

    【讨论】:

    • 是什么让 OP 的原始模式“不起作用”?
    • @41686d6564 我认为使用regexp_extract 而不是regexp_extract_all,但我没有使用presto 的经验。
    • 感谢您的帮助。不幸的是,我正在编写此查询的程序不允许我使用 regex_extract_all。更糟糕的是,由于某种原因,您的解决方案在该程序中不起作用(即使我认为它是正确的)。在带有 [0-9A-E]* 的部分,有没有办法排除 1?所以它只搜索0、2-9?抱歉,正则表达式不太好
    • @user9592573 “有办法排除 1 吗?” 这不正是这个答案中的第二个模式吗?
    • @user9592573 如果获取第二个值的单个组也可以,可以使用1[A-E][02-9A-E]*(1[A-E])regex101.com/r/F4T6Bk/1
    猜你喜欢
    • 2011-02-04
    • 2010-12-25
    • 1970-01-01
    • 2016-11-21
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 1970-01-01
    相关资源
    最近更新 更多