所以,我正在用一种酶(为了你的好奇心,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 :(得分: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
的简单实现可能会陷入无限循环,在第一个字符之前重复与指针匹配。看来,一旦匹配发生而没有推进指针,算法强制将指针前进一个字符。这解释了您的案例中的结果: