在perl中减去后文件的绝对值

File's absolute values after subtraction in perl

我有下面的table(带/t分隔符的txt文件),我想写一个脚本,每次将下一行的值减去上一行的值,然后获得绝对值每个值。

43 402 51 360 66

61 63 67 66 65

63 60 69 63 58

65 53 89 55 57

103 138 135 135 85

例如:

腹肌(61-43)腹肌(63-402)腹肌(67-51)腹肌(66-360)腹肌(65-66)

abs(63-61) abs(60-63) abs(69-67) abs(63-66) abs(58-65) 等..

这是我写的

#!/usr/bin/perl -w
use strict;
use warnings;

my $filename = '/home/kgee/Desktop/gene_gangs/table_gangs/table_ony_numbers';
open(my $fh, '<:encoding(UTF-8)', $filename)
or die "Could not open file '$filename' $!";

$newtable=0;
$i=0;
$j=1;
while (my $row = <$fh>) {
chomp $row;
print "$row\n";

my @numbertable = split//,$filename;

for (@numbertable){
  $newtable[$j]= ($i+2) -($i+1);
  $temp[$i]= abs($newtable[$j]);
   $newtable=$tepm[$i];
my @newtable= split//,$newtable;

print("@newtable","\n");
    $i=$i+1; 
 }

}

我有很多错误都是 "global symbol XXX requires explicit package name (did you forget to declare "my XXX"?) at line XXX?" 我在网上读到,要解决这个问题,您已经删除了 use warnings;(from the begging) ,这是不推荐的,或者在块外(而不是在块内!)声明变量。我都试过了,但仍然有一些警告。

好的,首先:永远不要"turn off warnings"。您会关闭汽车上的警告,并希望一切顺利吗?那里有警告是因为有些事情你需要修复,而不是忽略。

my用于在第一次使用时声明一个变量。

这个就这么简单

my $newtable = 0;

您还在代码中添加了一些混淆路径,我建议您排序:

  • 正确缩进
  • 不要使用 $newtable@newtable - 它们是不同的变量,很容易混淆 $newtable;$newtable[0];
  • 您有 $temp$tepm - 这正是 use warnings 帮助您识别的类型。
  • 拆分 $filename 以获得 @numbertable - 我很确定这不会按照您的意愿进行,因为它将字符串 '/home/kgee/Desktop/gene_gangs/table_gangs/table_ony_numbers' 拆分为字符。您的意思是 split /\t/, $row; 吗?
  • 同样 my @newtable= split//,$newtable; ...我认为这也不会像您认为的那样,因为 $newtable 是 'just' 零,正如您程序中前面实例化的那样,而您永远不要修改它。
  • for (@numbertable) 迭代 table 中的每个元素(拆分行?)但您永远不会使用迭代器。 $_ 每次迭代都设置为当前元素。但它与 $i$j 没有任何关系,而且您实际上似乎根本没有修改 $j - 所以它保持为零。
  • perl -wuse warnings; 是多余的。您可能应该坚持使用一个或另一个。 (我个人更喜欢 use warnings;use strict;)。

实际上,我看代码越多,我就越清楚它实际上不起作用,而且您的问题 运行 比您最初的警告更严重。

怎么样:

#!/usr/bin/perl
use strict;
use warnings;

use Data::Dumper;

my @previous_row; 
my @new_table;

##iterate line by line - use your file handle here, <DATA> is a special case. 
while ( <DATA> ) {
  #strip trailing linefeed. 
  chomp;
  #split this row on any whitespace (which includes tabs) 
  my @row = split; 
  #Handle first iteration - can't subtract 'previous row' if there isn't one. 
  if ( @previous_row ) { 
     my @new_row; 
     #iterate the current row
     foreach my $element ( @row ) { 
       #grab the elements off the previous row - note "shift" modifies it, and this will
       #break if you've got uneven length rows. (But you don't, and I'll leave it to you to handle that if you do. 
       my $previous_row_element = shift @previous_row; 
       #calculate new value
       my $value = abs ( $element - $previous_row_element ); 
       #stash new value into new row. 
       push @new_row, $value; 
     }
     #new row is complete, so push it into the new table. 
     push @new_table, \@new_row; 
   }
   #Update 'previous row' with the contents of the current row. 
   @previous_row = @row;
}

#lazy mode output. Iterating the array and printing values in the format you want 
#is up to you. 
print Dumper \@new_table;

__DATA__
43 402 51 360 66
61 63 67 66 65
63 60 69 63 58
65 53 89 55 57
103 138 135 135 85

请参阅@Sobrique 的回答,以获得对您的脚本的一些问题的出色解释。我只是在这里提出一种替代方法:

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

my $filename = 'table_only_numbers';
open(my $fh, '<:encoding(UTF-8)', $filename)
  or die "Could not open file '$filename': $!";

my @row1;
while (my $row = <$fh>) {
    chomp $row;
    my @row2 = split " ", $row;
    if (@row1) {
        die "Bad format!" if @row1 != @row2;
        my @new = map { abs ($row2[$_] - $row1[$_]) } 0..$#row2;
        say join " ", @new;
    }
    @row1 = @row2;
}
close $fh;