2011-05-18 138 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