Python 正则表达式:匹配从简单字符串派生的多个模式

Python 正则表达式:匹配从简单字符串派生的多个模式,python,regex,d,fastq,Python,Regex,D,Fastq,我有以下任务: 从30个字符长的模式序列开始(实际上是DNA序列,以免称之为P30),我需要在文本文件中找到所有以精确的P30开头的行(^Agatacag…),然后是30、28和最多10个字符中的最后29个字符。我所需要做的只是删除模式的第一个字符并继续搜索。 为了简单起见,我目前需要精确匹配,但是允许长时间(20-30个字符长的模式)的1个不匹配会更好 我目前的解决方案是创建一个shell文件,每行有一个被截断的模式,grep[1]将其删除。这意味着我正在阅读巨大的、很少GB的文本文件20x,

我有以下任务: 从30个字符长的模式序列开始(实际上是DNA序列,以免称之为P30),我需要在文本文件中找到所有以精确的P30开头的行(^Agatacag…),然后是30、28和最多10个字符中的最后29个字符。我所需要做的只是删除模式的第一个字符并继续搜索。 为了简单起见,我目前需要精确匹配,但是允许长时间(20-30个字符长的模式)的1个不匹配会更好

我目前的解决方案是创建一个shell文件,每行有一个被截断的模式,grep[1]将其删除。这意味着我正在阅读巨大的、很少GB的文本文件20x,这可能需要一天时间

我可以切换到python,创建一个包含所有必需模式的列表/元组,然后只读取一次文件,而不是每个序列循环20次,使用pypy加快速度

  • 问题1:有没有比这种循环更快的正则表达式
  • 问题2:通过切换到更快的编译语言来加速它有意义吗?(我试图理解德朗)
[1] 因为它是DNA序列,并且要搜索的输入是FASTQ格式,所以我使用fqgrep: 使用tre库:

编辑_1 更改(缩短模式)的示例。仅显示前几个步骤/较短的模式:

^abcde
^bcde
^cde
或者,如果您喜欢将其作为DNA:

^GATACCA
^ATACCA
^TACCA
编辑_2 简单的grep并不能真正解决这个问题。我需要对FASTQ格式的每4行进行后期处理,其中只有第2行匹配。如果我不使用fqgrep,那么我必须:

阅读输入的4行内容
-检查第2行(序列)是否以20种模式(P30-P10)中的任何一种开始
-如果我得到匹配,我需要剪切第2行和第4行的前N个字符,其中N代表匹配模式的长度 -在输出/写入文件行打印输出#1-$4,不匹配,不执行任何操作

对于内部解决方案,我可以尝试使用GNU并行将输入文件拆分为4百万个谎言块,并以这种方式加快速度。但是,如果我想让每一个新软件都能被其他人使用,我就要求最终用户安装更复杂的广告

**编辑3** Vyctor中的正则表达式和匹配行的简单示例:

starting P30 regex 
^agacatacagagacatacagagacatacag
matching sequence:
^agacatacagagacatacagagacatacagGAGGACCA

P29: 
^gacatacagagacatacagagacatacag
matching sequence:
^gacatacagagacatacagagacatacagGACCACCA

P28: 
^acatacagagacatacagagacatacag
matching sequence:
^acatacagagacatacagagacatacagGATTACCA
我去掉左边的字符/DNA碱基(或者说DNA中的5素数端),因为这是真实酶降解这些序列的方式。一旦发现正则表达式序列,它本身就不有趣了。所需的输出是正则表达式之后的读取序列。在上面的例子中,它是在超级情况下,然后可以在下一步映射到基因组。 应该强调的是,除了这个玩具示例之外,我在正则表达式模式之后获得了更长的、先验未知的和变化的序列。在现实世界中,我不必处理DNA的大写/小写字符(所有字符都是大写),但我在搜索模式的序列中可能会遇到Ns(=未知DNA碱基)。在一级近似中可以忽略这些,但对于更敏感的算法版本,可能应将其视为简单的不匹配。在理想情况下,不计算给定位置的简单不匹配,而是计算更复杂的惩罚,考虑到以FASTQ格式存储的每个4行长序列记录的第4行中存储的DNA序列质量值:


但这要复杂得多,到目前为止,“只读取与regex完全匹配的数据”方法已经足够好了,并且使后续步骤更容易分析

您可以通过编程方式生成如下所示的正则表达式。
它只是行开始或下一个字符的渐进交替

这将使您能够进行单遍搜索。
您只需获取匹配的字符串长度即可告诉您
你在哪里

注意-使用多行模式

 #  (?:^|a)(?:^|g)(?:^|a)(?:^|c)(?:^|a)(?:^|t)(?:^|a)(?:^|c)(?:^|a)(?:^|g)(?!^)0123456789

 (?: ^ | a )      # P30
 (?: ^ | g )      # P29
 (?: ^ | a )      # P28
 (?: ^ | c )      # P27
 (?: ^ | a )      # P26
 (?: ^ | t )      # P25
 (?: ^ | a )      # P24
 (?: ^ | c )      # P23
 (?: ^ | a )      # P22
 (?: ^ | g )      # P21
                  # ..
                  # P11
 (?! ^)           # Not beginning of line
 0123456789       # P10 - P1
例如,匹配以下各项:

agacatacag0123456789
cag0123456789
gacatacag0123456789
acatacag0123456789
acag0123456789
catacag0123456789
catacag0123456789
0123456789
atacag0123456789
tacag0123456789
ag0123456789
g0123456789
但不是这些:

agaatacag0123456789
ca0123456789
gacataca0123456789
acaacag0123456789
acg0123456789
cataca0123456789
caacag0123456789
123456789
atacg0123456789
tcag0123456789
ag012456789
g012356789
更新

这是一个图形说明,单个正则表达式可以替换所有30个正则表达式。
实际上不需要30个单独的正则表达式,只需要1个常量正则表达式。
在本例中,集群组被替换为捕获组,这样您就可以看到它在做什么

 # (^|G)(^|A)(^|T)(^|A)(^|C)(^|C)(?!^)A

 ( ^ | G )        # (1)
 ( ^ | A )        # (2)
 ( ^ | T )        # (3)
 ( ^ | A )        # (4)
 ( ^ | C )        # (5)
 ( ^ | C )        # (6)
 (?! ^ )          # Not beginning of line
 A
输入,6行:

GATACCA
ATACCA
TACCA
ACCA
CCA
CA
输出:

 **  Grp 0 -  ( pos 0 , len 7 ) 
GATACCA  
 **  Grp 1 -  ( pos 0 , len 1 ) 
G  
 **  Grp 2 -  ( pos 1 , len 1 ) 
A  
 **  Grp 3 -  ( pos 2 , len 1 ) 
T  
 **  Grp 4 -  ( pos 3 , len 1 ) 
A  
 **  Grp 5 -  ( pos 4 , len 1 ) 
C  
 **  Grp 6 -  ( pos 5 , len 1 ) 
C  

------------------------------

 **  Grp 0 -  ( pos 9 , len 6 ) 
ATACCA  
 **  Grp 1 -  ( pos 9 , len 0 )  EMPTY 
 **  Grp 2 -  ( pos 9 , len 1 ) 
A  
 **  Grp 3 -  ( pos 10 , len 1 ) 
T  
 **  Grp 4 -  ( pos 11 , len 1 ) 
A  
 **  Grp 5 -  ( pos 12 , len 1 ) 
C  
 **  Grp 6 -  ( pos 13 , len 1 ) 
C  

------------------------------

 **  Grp 0 -  ( pos 17 , len 5 ) 
TACCA  
 **  Grp 1 -  ( pos 17 , len 0 )  EMPTY 
 **  Grp 2 -  ( pos 17 , len 0 )  EMPTY 
 **  Grp 3 -  ( pos 17 , len 1 ) 
T  
 **  Grp 4 -  ( pos 18 , len 1 ) 
A  
 **  Grp 5 -  ( pos 19 , len 1 ) 
C  
 **  Grp 6 -  ( pos 20 , len 1 ) 
C  

------------------------------

 **  Grp 0 -  ( pos 24 , len 4 ) 
ACCA  
 **  Grp 1 -  ( pos 24 , len 0 )  EMPTY 
 **  Grp 2 -  ( pos 24 , len 0 )  EMPTY 
 **  Grp 3 -  ( pos 24 , len 0 )  EMPTY 
 **  Grp 4 -  ( pos 24 , len 1 ) 
A  
 **  Grp 5 -  ( pos 25 , len 1 ) 
C  
 **  Grp 6 -  ( pos 26 , len 1 ) 
C  

------------------------------

 **  Grp 0 -  ( pos 30 , len 3 ) 
CCA  
 **  Grp 1 -  ( pos 30 , len 0 )  EMPTY 
 **  Grp 2 -  ( pos 30 , len 0 )  EMPTY 
 **  Grp 3 -  ( pos 30 , len 0 )  EMPTY 
 **  Grp 4 -  ( pos 30 , len 0 )  EMPTY 
 **  Grp 5 -  ( pos 30 , len 1 ) 
C  
 **  Grp 6 -  ( pos 31 , len 1 ) 
C  

------------------------------

 **  Grp 0 -  ( pos 35 , len 2 ) 
CA  
 **  Grp 1 -  ( pos 35 , len 0 )  EMPTY 
 **  Grp 2 -  ( pos 35 , len 0 )  EMPTY 
 **  Grp 3 -  ( pos 35 , len 0 )  EMPTY 
 **  Grp 4 -  ( pos 35 , len 0 )  EMPTY 
 **  Grp 5 -  ( pos 35 , len 0 )  EMPTY 
 **  Grp 6 -  ( pos 35 , len 1 ) 
C  

如果我理解正确,则您有要匹配的预设:

agacatacag
然后匹配匹配的行:

re:agacatacag
30:Agacatacag Agacatacag
29:AgacatacagAgacatacac
28:Agacataccc
你不需要正则表达式,你只需要找到两行之间的差异,因为它是DNA,我假设字符串
abcde
aebcd
的差异为4,因为所有序列都需要在正确的位置

如果顺序无关紧要,并且您只想搜索至少匹配28个字符的行,那么您可以直接搜索

如果您需要的匹配实际上是以正确的顺序开始的,那么您可以在第一个差异位于点
=28

reg = 'agacatacagagacatacagagacatacag'
for row in file:
    diffs = list(i for i,(a1,a2) in enumerate(zip(s1,s2)) if a1!=a2)
    if not len(diffs):
        difference = len(reg)
    else:
        difference = diffs[0]

    if difference == 30: # First difference is at last offset

我认为你的问题是很好的结束,因为你不清楚你在问什么。请添加一些示例,说明您试图如何处理“这是源代码,这是预期的输出”。如果您添加当前的
sh
文件,也会有所帮助。也可以考虑这些很棒的答案:只需选择前20个字符匹配:<代码> ^?g?a?c?a?c?a?g?……/代码>我为你张贴了一些更新信息。实际上,当您只需要一个常量表达式时,不需要检查30个单独的正则表达式。例如,在edit_2中,匹配长度减去P30字符的整个长度会告诉您要修剪多少。这是一个简单的减法。这真的很简单。你的例子很好,但我认为
reg = 'agacatacagagacatacagagacatacag'
for row in file:
    diffs = list(i for i,(a1,a2) in enumerate(zip(s1,s2)) if a1!=a2)
    if not len(diffs):
        difference = len(reg)
    else:
        difference = diffs[0]

    if difference == 30: # First difference is at last offset