为什么在使用正先行 (?=...) 时,regexp_matches 函数会得到空响应

Why do I get empty response for regexp_matches function while using positive lookahead (?=...)

为什么下面的代码 return 只是空括号 - {''}。如何让它 return 匹配字符串?

SELECT regexp_matches('ATGCATGCATGCCAACAACAACCTGTCAAGTGAGT','(?=..CAA)','g');

预期输出为:

regexp_matches 
----------------
{GCCAA}
{AACAA}
{AACAA}
{GTCAA}
(4 rows)

而是 return 如下:

 regexp_matches 
----------------
 {""}
 {""}
 {""}
 {""}
(4 rows)

我实际上有一个更复杂的查询,它需要正向前瞻以覆盖字符串中所有出现的模式,即使它们重叠。

Lookahead 是一个零宽度断言。它不匹配任何东西。如果您将正则表达式更改为正则表达式 match/capture,您将得到一个结果。为了匹配您的情况下后跟 CAA 的任意两个字符,可能不需要先行。

  • 使用前瞻有一个问题,即前瞻本身不是匹配的一部分,但它允许重叠搜索
  • 如果不使用前瞻,您将失去重叠搜索的能力。

使用 Powershell,您可以遍历前瞻返回的索引,并将其用作搜索字符串的索引以获取匹配项

$string = 'ATGCATGCATGCCAACAACAACCTGTCAAGTGAGT'
$r = [regex]::new('(?=..CAA)')
$r.Matches($string) | % {$string.Substring($_.Index, 5)}

returns

GCCAA
AACAA
AACAA
GTCAA

我不知道如何将其转换为 PostgreSQL (或者如果可能的话)

嗯,这不是很漂亮,但你可以在没有正则表达式或自定义函数的情况下做到这一点。

WITH data(d) as (
  SELECT * FROM (VALUES ('ATGCATGCATGCCAACAACAACCTGTCAAGTGAGT')) v
)
SELECT substr(d, x, 5) AS match
FROM data
JOIN LATERAL (SELECT generate_series(1, length(d))) g(x) ON TRUE
WHERE substr(d, x, 5) LIKE '__CAA'
;
 match
-------
 GCCAA
 AACAA
 AACAA
 GTCAA
(4 rows)

基本上,获取字符串的每五个字母切片并查看它是否匹配 __CAA。

您可以将 generate_series(1, length(d)) 更改为 generate_series(1, length(d)-4),因为最后一个永远不会匹配,但如果匹配字符串的长度发生变化,您必须记得更新它。

更新:
显然它不会捕获断言内部,没关系,因为
您真正需要的是前 2 个字符,可以安全地
消费。它只会给你每行的前 2 个字符,但是
因为你知道最后3个,你可以很容易地加入集合元素
使用 CAA 常量。

试试这个

..(?=CAA)

大功告成。
如果我知道奇怪的 sql 语言,我可以向您展示如何进行连接。

输出现在应该是

match
-------
GC  
AA  
AA  
GT  
(4 rows)  

这是重叠匹配所需的正则表达式。

(?=(..CAA))

https://regex101.com/r/eJ36zb/1

我认为您只需要捕获第 1 组的 sql 语句:

SELECT regexp_matches('ATGCATGCATGCCAACAACAACCTGTCAAGTGAGT','(?=(..CAA))','g');

格式化正则表达式

 (?=
      ( . . CAA )                   # (1)
 )

你的结果中出现空字符串的原因是
你没有给表达式任何消费和
没有什么可捕捉的。

也就是说,它在正确的地方匹配,但没有消耗或捕获任何东西。
所以,这样做允许重叠和捕获所以它
现在应该出现在输出中。