首页 > 解决方案 > 为什么正则表达式中的一长串 ?char?char 等.. 这么慢

问题描述

我正在尝试创建一个正则表达式以符合以下(iupac 生物学)规则:

<    Any characters before a < are considered optional and will be matched after the subsequence text has been found

换句话说,这意味着:

给定 CAT<ATTT,我想找到任何与 ATTT 完全匹配的文本,然后如果在该匹配之前有一个 T,我想将它包含在匹配中,如果在 T 之前有一个 A,我想也包括它。如果在 AI 之前还有一个 C 也想包含它。

以下是应用该规则时的示例:

IUPAC生物学插入符号规则

更多示例:

CAT<ATTT (example pattern)
CATA ATTT (left side unmatched, right side matched)
CG ATATTT (left side unmatched, right side matched)
GGGT<GAGGGGGG  (example pattern)
T GGTGAGGGGGG  (left side unmatched, right side matched)
GGG GAGGGGGG   (left side unmatched, right side matched)

为了满足这个规则。我基本上为“<”之前的所有字符添加一个问号。例如,

TTGATAGCCATCATCATATCGAAGTTTCACTACCCTTTTTCCATTTGCCATCTATTGAAGTAATAATAGGC<GCATG

变成:

T?T?G?A?T?A?G?C?C?A?T?C?A?T?C?A?T?A?T?C?G?A?A?G?T?T?T?C?A?C?T?A?C?C?C?T?T?T?T?T?C?C?A?T?T?T?G?C?C?A?T?C?T?A?T?T?G?A?A?G?T?A?A?T?A?A?T?A?G?G?C?GCATG

但是我发现添加一堆可选的?字符会创建一个非常慢的正则表达式(至少在 chrome 浏览器中运行时)。您可以通过在浏览器中运行以下代码自己尝试:

"GACGTCTTATGACAACTTGACGGCTACGCATGATCATTCACTT".match("C?A?T?A?T?CT?T?G?A?T?A?G?C?C?A?T?C?A?T?C?A?T?A?T?C?G?A?A?G?T?T?T?C?A?C?T?A?C?C?C?T?T?T?T?T?C?C?A?T?T?T?G?C?C?A?T?C?T?A?T?T?G?A?A?G?T?A?A?T?A?A?T?A?G?G?C?GCATG", "gi")

或者,如果这对您来说很快,请运行这个:

"GACGTCTTATGACAACTTGACGGCTACGCATGATCATTCACTT".match("T?T?G?A?T?A?G?C?C?A?T?C?A?T?C?A?T?A?T?CT?T?G?A?T?A?G?C?C?A?T?C?A?T?C?A?T?A?T?CT?T?G?A?T?A?G?C?C?A?T?C?A?T?C?A?T?A?T?C?G?A?A?G?T?T?T?C?A?C?T?A?C?C?C?T?T?T?T?T?C?C?A?T?T?T?G?C?C?A?T?C?T?A?T?T?G?A?A?G?T?A?A?T?A?A?T?A?G?G?C?GCATG", "gi")

我的问题是两方面的。首先,为什么这个正则表达式这么慢?其次,如何使用正则表达式以高效的方式实现上图所示的规则(特别是“<”和“>”规则)?(或者也许不可能?)

如果您有任何澄清性问题,请提出。

非常感谢!

标签: regex

解决方案


一个看起来像这样的正则表达式:

(CAT|AT|T)?ATTTT

很适合我。它比我之前尝试使用的(损坏的)解决方案性能更高。

注意:我发现使用 reg.exec 查找包含我不想要的中间结果。因此我使用的代码看起来像:

[..."CGCATATTT".matchAll("(CCAT|CAT|AT|T)?ATTT", "gi")]

感谢@WiktorStribiżew 和我的同事帮助我找到了一个好的解决方案!


推荐阅读