Perl捕获并添加到字符串的结尾

时间:2017-06-09 14:07:18

标签: regex perl

我有一个包含很多这样的行的文件:

ChrVIII_A_nidulans_FGSC_A4  AspGD   gene    3861520 3863875 .   +   .   ID=AN0338;Name=AN0338;Gene=CYP680A1;Note=Putative%20cytochrome%20P450;orf_classification=Uncharacterized;Alias=ANIA_00338,ANID_00338

我感兴趣的区域是;Gene=_____; - =;之间的内容。

如果这个区域存在,我想将它附加到行的末尾,附加到前面。如果它不存在我想打印线仍然!

ChrVIII_A_nidulans_FGSC_A4  AspGD   gene    3861520 3863875 .   +   .   ID=AN0338;Name=AN0338;Gene=CYP680A1;Note=Putative%20cytochrome%20P450;orf_classification=Uncharacterized;Alias=ANIA_00338,ANID_00338,CYP680A1

这是我在Perl中尝试过的,我不知道它为什么不起作用。

use strict;
use warnings;
open(SOURCE,"<annotation.gff") or die "Source file not found!\n";

my $line1;
foreach $line1(<SOURCE>)            #iterating over SOURCE file
{
if($line1=~/Gene\=([a-zA-Z0-9\-]+)\;/)
printf "$line1,$1";
}
else {printf "$line1";}
}

有谁能告诉我我做错了什么?

2 个答案:

答案 0 :(得分:3)

让我们查看您的代码:

use strict;
use warnings;

好。但是,尝试运行代码会产生:

  

syntax error at ss.pl line 9, near ") printf" syntax error at ss.pl line 11, near "else"

这意味着您没有发布您运行的代码,因此我们无法真正信任它。不要这样做。将问题减少到其他人可以运行的小型自包含脚本。

open(SOURCE,"<annotation.gff") or die "Source file not found!\n";
  • 不要使用SOURCE之类的裸字文件句柄。相反,请使用词法文件句柄。

  • 不要硬编码您要打开的文件的名称。这样做很难准确地传达程序在发生故障时无法打开的文件名。

  • 在错误消息中,包含您的程序遇到的实际错误,而不是硬编码您的无根据的假设。

  • 不要使用open的两个参数形式,特别是如果您希望灵活地将文件名指定为命令行参数,而不是每次都必须编辑脚本获取一个新的输入文件。也就是说,使用

    my $annotation_file = 'annotation.gff';
    open my $source, '<', $annotation_file
        or die "Failed to open annotation source '$annotation_file': $!";
    
  • 不要为循环范围之外的循环声明迭代变量。也就是说,而不是:

    my $line1;
    foreach $line1 ( ... )
    

    使用

    foreach my $line1 ( ... )
    
  • 但是,当然,您不应该使用for循环来迭代文件的内容,因为这样做会使您的程序 slurp (即读取整个内容)将文件作为行列表存入内存。这使得程序的内存占用量取决于其输入的大小,而不是最长行的大小。另外,删除1后缀:您正在遍历文件中的每个行,而不仅仅是第一行。

     while (my $line = <$source>) {
    
  • 如果您只是打印普通字符串,请不要使用printf。也就是说,使用printf "$line1,$1"

  • 而不是print "$line,$1\n"
  • 而且,这带来了另一个问题。当您阅读该行时,您永远不会删除该行的新行。因此,您打印的字符串为"...\n...",这会产生将捕获的字符串前置到下一行开头的效果。

这给我们带来了有用的东西:

use strict;
use warnings;

my $annotation_file = 'annotation.gff';

open my $source, '<', $annotation_file
    or die "Cannot open annotation source '$annotation_file': $!";

while (my $line = <$source>) {
    if( $line =~ /Gene = ( [^;]+ ) ;/x ) {
        chomp $line;
        print join(',' => $line, $1), "\n";
    }
    else {
        print $line;
    }
}

答案 1 :(得分:0)

试试这个:

use strict;
use warnings;
open(my $fh, '<', 'annotation.gff') or die $!;

while (<$fh>) {
    chomp;
    /Gene=([a-zA-Z0-9\-]+)\;/ and $_ .= ",$1";
    print "$_\n";
}

close $fh;