2011-05-18 135 views
8

因此,我正在用一种酶(为了您的好奇心,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中都支持零宽度前瞻断言。我在做什么错我的正则表达式?

+0

你使用什么方法? '字符串#扫描','字符串#拆分或其他东西? – 2011-05-18 23:38:11

+3

+1这真是个好问题。我没有想到你得到的结果,进一步的分析告诉我一些关于正则表达式处理重复零宽度匹配的方法。 – Phrogz 2011-05-19 03:01:18

+0

您的陈述“在B或D编码的蛋白质之前切割”,我有点困惑。根据我的理解,** B **是** D或N(不知道残基是Asp还是Asn)的单字母代码? Aspn能否在Asn之前分裂? – tomd 2011-05-21 19:00:41

回答

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,并在此之后继续。
+0

也许我应该简化,因为其他答案似乎工作,但这是我真正想要的:理解!感谢您解释为什么我的正则表达式被破坏! – Ryanmt 2011-05-19 15:06:06

+0

@Ryanmt我很高兴我能帮上忙。我还修改了我的正则表达式,向您展示了一种更简单的方法来捕获序列的末尾,如果您想使用这种方法而不是简单的基于分割的解决方案。 – Phrogz 2011-05-19 16:57:00

+0

啊。我已经阅读过有关这方面的内容,但并未将其应用于我的问题。谢谢! – Ryanmt 2011-05-19 17:48:33

9

基本上,你想在每个B或D之前切断你的字符串?

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

给你

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

很好的答案,干净。谢谢! – Ryanmt 2011-05-19 17:49:20