正则表达式蛋白质消化

时间:2011-05-18 23:30:24

标签: ruby regex bioinformatics

所以,我正在用一种酶(为了你的好奇心,Asp-N)消化蛋白质序列,它在单字母编码序列中由B或D编码的蛋白质之前切割。我的实际分析使用String#scan进行捕获。我试图弄清楚为什么以下正则表达式不能正确消化它......

(\w*?)(?=[BD])|(.*\b)

其中存在先行词(.*\b)以捕获序列的结尾。 为:

MTMDKPSQYDKIEAELQDICNDVLELLDSKGDYFRYLSEVASGDN

这应该是这样的:[MTM, DKPSQY, DKIEAELQ, DICN, DVLELL, DSKG, ... ]但是错过了序列中的每个D.

我一直在使用http://www.rubular.com进行故障排除,它运行在1.8.7上,虽然我也在1.9.2上测试了这个REGEX但无济于事。据我所知,在两个版本的ruby中都支持零宽度前瞻断言。我的正则表达式做错了什么?

2 个答案:

答案 0 :(得分:9)

基本上,你想在每个B或D之前剪掉字符串吗?

"...".split(/(?=[BD])/)

给你

["MTM", "DKPSQY", "DKIEAELQ", "DICN", "DVLELL", "DSKG", "DYFRYLSEVASG", "DN"]

答案 1 :(得分:3)

支持这一点的最简单方法是拆分零宽度前瞻:

s = "MTMDKPSQYDKIEAELQDICNDVLELLDSKG"
p s.split /(?=[BD])/
#=> ["MTM", "DKPSQY", "DKIEAELQ", "DICN", "DVLELL", "DSKG"]

要了解您的解决方案出了什么问题,让我们首先看一下你的正则表达式与一个有效的正则表达式:

p s.scan(/.*?(?=[BD]|$)/)
#=> ["MTM", "", "KPSQY", "", "KIEAELQ", "", "ICN", "", "VLELL", "", "SKG", ""]

p s.scan(/.+?(?=[BD]|$)/)
#=> ["MTM", "DKPSQY", "DKIEAELQ", "DICN", "DVLELL", "DSKG"]

问题在于,如果您可以捕获零个字符并仍然匹配零宽度前瞻,则无需推进扫描指针即可成功。让我们看一个更简单但相似的测试用例:

s = "abcd"
p s.scan //      # Match any position, without advancing
#=> ["", "", "", "", ""]

p s.scan /(?=.)/ # Anywhere that is followed by a character, without advancing
#=> ["", "", "", ""]

String#scan的简单实现可能会陷入无限循环,在第一个字符之前重复与指针匹配。看来,一旦匹配发生而没有推进指针,算法强制将指针前进一个字符。这解释了您的案例中的结果:

  1. 首先,它匹配所有字符,直到B或D,
  2. 然后它匹配B或D之前的零宽度位置,而不移动字符指针
  3. 结果算法将指针移过B或D,然后继续。