Абсолютные значения файла после вычитания в perl - PullRequest
0 голосов
/ 27 января 2020

У меня есть таблица ниже (txt файл с разделителем / t), и я хочу написать скрипт, который будет вычитать каждый раз значения следующей строки из предыдущей строки, а затем получать абсолютное значение каждого значения.

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

Например:

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

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

Это что я написал.

#!/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; 
 }

}

Я получил много ошибок, все они: «глобальный символ XXX требует явного имени пакета (вы забыли объявить« мой XXX »?) в строке XXX?» Я читал в Интернете, что для того, чтобы перешагнуть через эту проблему, вы должны удалить предупреждения use (из самого начала) , которые не рекомендуются, или объявить переменную вне блока (а не внутри!). Я пробовал оба, но все же у меня есть некоторые предупреждения.

Ответы [ 2 ]

2 голосов
/ 27 января 2020

OK first off: Никогда не «выключайте предупреждения». Вы бы отключили предупреждения на своей машине и ожидали, что это хорошо закончится? Предупреждения есть, потому что нужно что-то исправить, а не игнорировать.

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 это «просто» ноль, как было показано ранее в вашей программе, и вы никогда не модифицируете его.
  • for (@numbertable) выполняет итерацию каждого элемента в этой таблице (разделенная строка?), Но вы никогда не используете итератор. $_ устанавливается на текущий элемент каждой итерации. Но это не имеет ничего общего с $i и $j, и вы на самом деле, кажется, вообще не изменяете $j - так что оно остается равным нулю.
  • perl -w и use 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
0 голосов
/ 27 января 2020

См. Ответ @ 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;
...