我有一个登记号和16S rrna序列的文件,我正在尝试删除所有RNA的行,并且只保留具有登录号和物种名称的行(并删除所有垃圾之间)。所以我的输入文件看起来像这样(在登录号前面有>):
> D50541 1 1409 1409bp rna Abiotrophia defectiva Aerococcaceae
CUGGCGGCGU GCCUAAUACA UGCAAGUCGA ACCGAAGCAU CUUCGGAUGC UUAGUGGCGA ACGGGUGAGU AACACGUAGA UAACCUACCC UAGACUCGAG GAUAACUCCG GGAAACUGGA GCUAAUACUG GAUAGGAUAU AGAGAUAAUU UCUUUAUAUU (......还有更多行)> AY538167 1 1411 1411bp rna Acholeplasma hippikon Acholeplasmataceae
CUGGCGGCGU GCCUAAUACA UGCAAGUCGA ACGCUCUAUA GCAAUAUAGG GAGUGGCGAA CGGGUGAGUA ACACGUAGAU AACCUACCCU UACUUCGAGG AUAACUUCGG GAAACUGGAG CUAAUACUGG AUAGGACAUA UUGAGGCAUC UUAAUAUGUU ...
我希望我的输出看起来像这样:
> D50541 Abiotrophia defectiva Aerococcaceae
> AY538167 Acholeplasma hippikon Acholeplasmataceae
我写的代码做了我想要的......对于大多数行。它看起来像这样:
#!/usr/bin/env python
# take LTPs111.compressed fasta and reduce to accession numbers with names.
import re
infilename = 'LTPs111.compressed.fasta'
outfilename = 'acs.fasta'
regex = re.compile(r'(>)\s(\w+).+[rna]\s+([A-Z].+)')
#remove extra letters and spaces
with open(infilename, 'r') as infile, open(outfilename, 'w') as outfile:
for line in infile:
x = regex.sub(r'\1\2 \3', line)
#remove rna sequences
for line in x:
if '>' in line:
outfile.write(x)
有时,代码似乎会跳过某些名称。例如,对于上面的第一个入藏号,我只回来了:
> D50541 Aerococcaceae
为什么我的代码可能会这样做?每个入藏号的输入看起来相同,“rna”和第一个名称之间的间距对于每一行(5个空格)是相同的。
感谢任何可能有想法的人!
答案 0 :(得分:2)
我仍然无法运行您的代码来获取声明的结果,但我想我知道问题是什么:
>>> line = '> AY538167 1 1411 1411bp rna Acholeplasma hippikon Acholeplasmataceae'
>>> regex = re.compile(r'(>)\s(\w+).+[rna]\s+([A-Z].+)')
>>> regex.findall(line)
[('>', 'AY538167', 'Acholeplasmataceae')]
问题在于,[rna]\s+
在单词的末尾与任意一个 r
,n
或a
匹配。并且,因为所有匹配都是贪婪的,没有预测或其他任何阻止它,这意味着它匹配n
末尾的hippikon
。
简单的解决方案是删除括号,使其与字符串 rna
匹配:
>>> regex = re.compile(r'(>)\s(\w+).+rna\s+([A-Z].+)')
如果您的任何物种或属可以以该字符串结尾,那将无效。有没有这样的名字?如果是这样,您需要提出一种更好的方法来描述1409bp
部分和rna
部分之间的界限。最简单的可能是查找由空格包围的rna
:
>>> regex = re.compile(r'(>)\s(\w+).+\s+rna\s+([A-Z].+)')
这是否真的是正确的,我不能不知道更多关于格式的内容,但希望你能理解我做得很好,以确认它是正确的(或者至少要问一些比我更聪明的问题问)。
它可能有助于调试添加捕获组的内容。例如,而不是:
(>)\s(\w+).+[rna]\s+([A-Z].+)
...搜索:
(>)(\s)(\w+)(.+[rna]\s+)([A-Z].+)
显然,您想要的捕获群现在是\1\3 \5
而不是\1\2 \3
...但最重要的是,您可以看到\4
中匹配的内容:
[('>', ' ', 'AY538167', ' 1 1411 1411bp Acholeplasma hippikon ', 'Acholeplasmataceae')]
所以,现在的问题是“为什么.+[rna]\s+
匹配'1 1411 1411bp Acholeplasma hippikon '
?有时上下文很重要,但在这种情况下,它没有。你不希望该组匹配该字符串在任何上下文中,但始终匹配它,因此这是您必须调试的部分。
此外,视觉正则表达式资源管理器经常有很大帮助。最好的可以为表达式的部分颜色和匹配的文本等着色,以向您展示正则表达式如何以及为什么正在做它所做的事情。
当然,您受限于那些在您的平台上或在线运行的人,并且使用Python语法。如果你小心和/或只使用简单的功能(如你的例子),perl / PCRE语法非常接近Python,而JavaScript / ActionScript也非常接近(要记住的一个很大的区别就是替换/ sub使用$
代替\1
)。
我没有一个好的在线版强烈推荐,但从快速浏览Debuggex看起来很酷。
答案 1 :(得分:0)
括号中的项目是字符类,因此通过设置正则表达式来查找“[rna]”,您要求的行 r,n或a,但不是全部三个。
此外,如果您想要的线条都具有“bp rna”模式,我会用它来拉动这些线条。通过逐行读取文件,以下内容对我来说是一个快速而肮脏的线条,例如:
regex = re.compile(r'^[\w\s]+bp rna .*$')
但是,再次,如果它就像在其中找到带有“bp rna”的行一样简单,你可以逐行读取文件并完全放弃正则表达式:
for line in file:
if "bp rna" in line:
print(line)
编辑:我没有仔细阅读请求,从而引爆了它。也许捕获和替换正则表达式会有帮助吗?
for line in file:
if "bp rna" in line:
subreg = re.sub(r'^(>[\w]+)\s[\d\s]+bp\srna\s([\w\s]+$)', r"\1 \2", line)
print(subreg)
输出:
>AY538166 Acholeplasma granularum Acholeplasmataceae
>AY538167 Acholeplasma hippikon Acholeplasmataceae
这应匹配您想要的事物之间的任何空格(制表符或空格)。