编辑行并从文件中删除行

时间:2013-05-06 18:33:31

标签: python regex

我有一个登记号和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个空格)是相同的。

感谢任何可能有想法的人!

2 个答案:

答案 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+在单词的末尾与任意一个 rna匹配。并且,因为所有匹配都是贪婪的,没有预测或其他任何阻止它,这意味着它匹配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

这应匹配您想要的事物之间的任何空格(制表符或空格)。