【问题标题】:Perl coding: How to extract part of a line in a text file and print it to an output filePerl 编码:如何提取文本文件中的部分行并将其打印到输出文件
【发布时间】:2012-11-07 12:20:14
【问题描述】:

我有一个如下所示格式的大文本文件 -

ID  SNP
FT  SNP 433
FT      /note="refAllele: T SNPstrains: 7083_1#5=C 7414_8#8=C 7480_8#49=C "
FT      /colour=1
FT  SNP 442
FT      /note="refAllele: T SNPstrains: 7065_8#2=C 7065_8#94=C 7083_1#2=C 7083_1#3=C 7083_1#41=C 7083_1#42=C 7083_1#43=C "
FT      /colour=1
FT  SNP 460
FT      /note="refAllele: T SNPstrains: 7564_8#14=C "
FT      /colour=1
FT  SNP 703
FT      /note="refAllele: G SNPstrains: 7521_5#39=A (non-synonymous) (AA Ala->Thr) "
FT      /colour=2
FT  SNP 937
FT      /note="refAllele: G SNPstrains: 7414_8#30=T (non-synonymous) (AA Val->Leu) "
FT      /colour=2
FT  SNP 1269
FT      /note="refAllele: G SNPstrains: 7480_7#22=A (synonymous) 7480_7#62=A (synonymous) "
FT      /colour=3
FT  SNP 1804
FT      /note="refAllele: T SNPstrains: 7414_7#66=A (non-synonymous) (AA Ser->Thr) 7414_8#44=A (non-synonymous) (AA Ser->Thr) 7521_6#54=A (non-synonymous) (AA Ser->Thr) "
FT      /colour=2

这是我使用的代码 -

$file="input file";
open IN, "$file";
open OUT, ">output file";
print OUT "Coordinate   No of Strains   AA Change\n";
while(<IN>){
    if(m/^FT\s+SNP\s+(\d+)/){
            $SNP=$1;        
    }elsif(m/^FT\s+\/note="(.*)"/){
        $line=$1;
        $count = ($line =~ tr/=/=/);
        $line =~ m/\((AA \w+->\w+)\)\s*$/;
        $change = $1 || "";
    }elsif(m/^FT\s+\/colour=(\d+)/){
        print OUT "$SNP $count $change\n" if $cod{$1} eq "non";
    }
}

目的是有一个类似于下面的输出文件(用于文本文件的上述部分)

Coordinates No of Strains AA Change
703         1             AA Ala->Thr
937         1             AA Val->Leu
1804        3             AA Ser->Thr

但是,当我将代码应用到文本文件时,我收到一个错误:Use of uninitialised values ($count or $change) in concatenation (.) or string at line 23. 有问题的行是

print OUT "$SNP $count $change\n" if $cod{$1} eq "non";

错误是指包含

的行
FT      /colour=2

即显示非同义突变的行,例如示例文本中的第 13 行。

请注意,我是编程新手,大部分代码不是我编写的。任何帮助将不胜感激!

非常感谢。

【问题讨论】:

  • 假设%cod 中有一些伪造的值,我没有收到给定输入的警告。我也没有得到你声称的输出。
  • 如果有的话,你会得到什么输出?
  • 我已经对整个文件重复使用此代码,这导致了我之前所说的输出,其中一部分如下所示 - Coordinate No of Strains AA Change 1299 1 AA Gin-&gt;His 3791 2 AA Val-&gt;Ala 4759 1 AA Gly-&gt;Ala 但是,如果我对示例文本执行此操作,我给了文件 2,我得到了这个输出 - Coordinate No of Strains AA Change 1299 和使用未初始化值的错误,就像我在第一个文件上使用代码时一样。
  • 您应该使用一个独立且正确的示例,其中输入、代码和输出都匹配。然后说明您的确切错误消息。最好只询问有关明确使用strictwarnings 的代码的问题,并检查诸如open 失败之类的简单错误。

标签: perl


【解决方案1】:

我使用更现代的编码标准重写了您的程序:

  • 我使用了use strict;use warnings;
  • 我使用空格来帮助澄清代码
  • 我对循环和 if/elsif 语句等内容使用了更现代的语法

我发现了一些小故障,但我很快就解决了这些问题。这是你的代码:

use strict;
use warnings;
use feature qw(say);

my $file = "input.txt";
my %cod = ( 1 => "red", 2 => "non", 3 => "green" );
open my $in, "<", "$file";
open my $out, ">", "output.txt";
say $out "Coordinate   No of Strains   AA Change";

my $SNP;
my $count;
my $change;
while ( my $line = <$in> ) {
    chomp $line;
    say qq(DEBUG: Line = "$line");
    if ( $line =~ /^FT\s+SNP\s+(\d+)/ ){
        $SNP = $1;        
        say qq(\$SNP = $1;);
    } 
    elsif ( $line =~ /^FT\s+\/note="(.*)"/) {
        my $note = $1;
        say qq(my \$note = $1);
        $count = ($note =~ tr/=/=/);
        $note =~ /\((AA \w+->\w+)\)\s*$/;
        $change = $1 || "";
    }
    elsif ( $line =~ /^FT\s+\/colour=(\d+)/ ) {
        say qq(Code = $1);
        if ( $cod{$1} eq "non" ) {
            printf $out "%-12.12s %-15.15s %s\n",  $SNP, $count, $change;
        }
    }
}

这是输出:

Coordinate   No of Strains   AA Change
703          1               AA Ala->Thr
937          1               AA Val->Leu
1804         3               AA Ser->Thr

这就是你要找的吗?

【讨论】:

  • 感谢您的回复,该输出是我正在寻找的,尽管当我将您的代码应用于整个文件时,我发现了这个错误:DEBUG: Line = "FT SNP 703" $SNP = 703 DEBUG: Line = "FT /note="refAllele: G SNPstrains: 7521_5#39=A (non-synonymous) (AA Ala->Thr) " DEBUG: Line = "FT / colour=2" Code = 2 使用未初始化Script.txt 第 33 行 第 xxxx 行的 printf 中的值($count 或 $change)。我以上述非同义更改为例,但似乎所有人都发生了。输出如你所说, 除了只列出所有 NS 变化的坐标。
  • 我有一些调试行。它们只是打印或说语句。我使用 DEBUG 语句来帮助调试我的程序。只需删除 say 语句即可摆脱调试内容。但是,如果你得到一个未初始化的值,你就不会像你想象的那样解析你的输入。使用无关的调试输出来找出为什么你得到一个未初始化的值。也许您的计数没有按预期工作。也许有几行不符合您的预期输入。看看为什么没有设置 $change$count
  • 我查看了完整的文件 - 我没有看到任何证据表明格式与我上面给出的示例文本有任何不同。我也尝试了你给我的代码,结果与未初始化的错误相同——它没有给我你上面发布的输出。
  • 有趣的是,我只是将您的代码应用到了我拥有的另一个格式相同的文件中,并且我没有收到未初始化值错误,并且按照上面的示例获得了正确的输出。这是否意味着一定存在我没有注意到的格式差异?
  • 如果您的程序中有错误,您可以调试它。在您读入时打印出所有行。然后,打印出 if 语句的哪一部分正在处理该行。打印出 if 语句是如何操作数据的。当您收到uninitialized 错误时(这就是您使用use warnings; 的原因,您可以查看调试输出的最后几行,看看可能导致问题的原因。毕竟,您已阅读该行,并且您会看到该行是如何被解析的。也许 $count 没有被设置,因为 tr /=/=/ 没有找到任何等号。通过查看输出来找出答案。
猜你喜欢
  • 2019-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-22
  • 1970-01-01
  • 2023-03-22
相关资源
最近更新 更多