正则expression式匹配多行文本块

在跨越多行的文本进行匹配时,获取Python正则expression式时遇到了一些麻烦。 示例文本是('\ n'是换行符)

some Varying TEXT\n \n DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF\n [more of the above, ending with a newline]\n [yep, there is a variable number of lines here]\n \n (repeat the above a few hundred times). 

我想捕捉两件事:'some_Varying_TEXT'部分,以及所有大写文本的行在它下面两行的捕捉(我可以去掉换行符)。 我已经尝试了几种方法:

 re.compile(r"^>(\w+)$$([.$]+)^$", re.MULTILINE) # try to capture both parts re.compile(r"(^[^>][\w\s]+)$", re.MULTILINE|re.DOTALL) # just textlines 

和很多的变化,没有运气。 最后一个似乎与一行一行的文字相符,这不是我真正想要的。 我可以赶上第一部分,没有问题,但我似乎无法赶上4-5行的大写字母。 我想match.group(1)是some_Varying_Text和组(2)是line1 + line2 + line3 +等,直到遇到空行。

如果有人好奇,它应该是组成蛋白质的一系列氨基酸。

尝试这个:

 re.compile(r"^(.+)\n((?:\n.+)+)", re.MULTILINE) 

我认为你最大的问题是,你期望^$锚匹配换行,但他们不。 在多行模式下, ^匹配紧跟在换行符后面的位置, $与匹配换行符之前的位置匹配。

请注意换行符可以由换行符(\ n),回车符(\ r)或回车符+换行符(\ r \ n)组成。 如果您不确定您的目标文本是否仅使用换行符,则应该使用这个更具包容性的正则expression式版本:

 re.compile(r"^(.+)(?:\n|\r\n?)((?:(?:\n|\r\n?).+)+)", re.MULTILINE) 

顺便说一句,你不想在这里使用DOTALL修饰符; 你依靠的是点符合除了换行之外的所有事物。

这将工作:

 >>> import re >>> rx_sequence=re.compile(r"^(.+?)\n\n((?:[AZ]+\n)+)",re.MULTILINE) >>> rx_blanks=re.compile(r"\W+") # to remove blanks and newlines >>> text="""Some varying text1 ... ... AAABBBBBBCCCCCCDDDDDDD ... EEEEEEEFFFFFFFFGGGGGGG ... HHHHHHIIIIIJJJJJJJKKKK ... ... Some varying text 2 ... ... LLLLLMMMMMMNNNNNNNOOOO ... PPPPPPPQQQQQQRRRRRRSSS ... TTTTTUUUUUVVVVVVWWWWWW ... """ >>> for match in rx_sequence.finditer(text): ... title, sequence = match.groups() ... title = title.strip() ... sequence = rx_blanks.sub("",sequence) ... print "Title:",title ... print "Sequence:",sequence ... print ... Title: Some varying text1 Sequence: AAABBBBBBCCCCCCDDDDDDDEEEEEEEFFFFFFFFGGGGGGGHHHHHHIIIIIJJJJJJJKKKK Title: Some varying text 2 Sequence: LLLLLMMMMMMNNNNNNNOOOOPPPPPPPQQQQQQRRRRRRSSSTTTTTUUUUUVVVVVVWWWWWW 

关于这个正则expression式的一些解释可能是有用的: ^(.+?)\n\n((?:[AZ]+\n)+)

  • 第一个字符( ^ )的意思是“从行首开始”。 请注意,它不符合换行符本身(与$相同,意思是“就在换行符之前”,但与换行符本身不匹配)。
  • 然后(.+?)\n\n意思是“尽可能less地匹配字符(所有字符都是允许的),直到达到两条新行”。 结果(没有换行符)放在第一组中。
  • [AZ]+\n表示“尽可能匹配大写字母,直到达到换行符。这定义了我将调用的文本行
  • ((?: textline )+)表示匹配一个或多个文本行,但不要将每行放在一个组中。 相反,将所有文本行放在一个组中。
  • 你可以在正则expression式中添加最后一个\n ,如果你想在最后执行一个双换行符。
  • 另外,如果你不确定你会得到什么types的换行符( \n\r\r\n ),那么只需修改正则expression式,用(?:\n|\r\n?)

如果每个文件只有一个氨基酸序列,我根本不会使用正则expression式。 就像这样:

 def read_amino_acid_sequence(path): with open(path) as sequence_file: title = sequence_file.readline() # read 1st line aminoacid_sequence = sequence_file.read() # read the rest # some cleanup, if necessary title = title.strip() # remove trailing white spaces and newline aminoacid_sequence = aminoacid_sequence.replace(" ","").replace("\n","") return title, aminoacid_sequence 

找:

 ^>([^\n\r]+)[\n\r]([AZ\n\r]+) 

1 = some_varying_text

\ 2 =所有CAPS的行

编辑(certificate这是有效的):

 text = """> some_Varying_TEXT DSJFKDAFJKDAFJDSAKFJADSFLKDLAFKDSAF GATACAACATAGGATACA GGGGGAAAAAAAATTTTTTTTT CCCCAAAA > some_Varying_TEXT2 DJASDFHKJFHKSDHF HHASGDFTERYTERE GAGAGAGAGAG PPPPPAAAAAAAAAAAAAAAP """ import re regex = re.compile(r'^>([^\n\r]+)[\n\r]([AZ\n\r]+)', re.MULTILINE) matches = [m.groups() for m in regex.finditer(text)] for m in matches: print 'Name: %s\nSequence:%s' % (m[0], m[1]) 

我的偏好。

 lineIter= iter(aFile) for line in lineIter: if line.startswith( ">" ): someVaryingText= line break assert len( lineIter.next().strip() ) == 0 acids= [] for line in lineIter: if len(line.strip()) == 0: break acids.append( line ) 

在这一点上,你有一些变化的文字作为一个string,酸作为一个string列表。 你可以做"".join( acids )来做一个单一的string。

我觉得这比多线正则expression式更令人沮丧(也更灵活)。