Как прочитать две строки из файла в perl

#perl

#perl

Вопрос:

Мне интересно, почему я не могу взять 2 строки в Perl, фрагмент моего кода

 #!/usr/bin/perl -w

open my $fh, "<", "data.txt" or die;

$line1 = <$fh>;
$line2 = <$fh>;

print $line1."n";
print $line2."n";

while(1){
    @rows = <$fh>;
    print "$rows[$e]";
    $e  ;
    print "$rows[$e]";
}
  

Это те данные, которые у меня есть в Data.txt

   5000    5000    12497500    0
  5000    5000    33258530    0
  5000    13    51822    0
  5000    13    130147    0
  5000    28    75016    0
  5000    28    181343    0
  5000    5000    4999    4999
  5000    5000    12580635    4999
  

Я искал возможные решения, я нашел здесь несколько интересных выводов http://www.perlmonks.org/?node_id=620077 , особенно эти

 my $fh = open("file");

for =$fh->$line1,$line2 {
  # do whatever with the two lines
}
  

и

 for (;;) {
   my $line1 = <$fh>;
   last if not defined $line1;

   my $line2 = <$fh>;
   last if not defined $line2;

   ...
}
  

Могу ли я также спросить for =$fh->$line1,$line2 , почему существует a = $ и почему это не работает или как это работает?

Любая помощь приветствуется!

Приветствия

ОБНОВЛЕНИЕ Хорошо, возможно, я чего-то не понимаю, но это та операция, которую я хотел выполнить из строк

 while(1){
    print '-'x50 . "n";
    my $line1 = <$fh>;

    if($line1 =~ /^s (d)s (d)s (d)s (d)s*$/){
        my $A1 = $1;
        my $B1 = $2;
        my $C1 = $3;
        my $D1 = $4;
    }
    last unless defined $line1;

    my $line2 = <$fh>;

    if($line2 =~ /^s (d)s (d)s (d)s (d)s*$/){
        my $A2 = $1;
        my $B2 = $2;
        my $C2 = $3;
        my $D2 = $4;
    }
    last unless defined $line2;

    my @type = ("AL", "PL", "RL", "AA", "PA", "RA", "AB", "PB", "RB", "AR", "PR", "RR", "AS", "PS", "RS", "AV", "PV", "RV");


    print("For $type[$i]n");
    print("Node : $A1n");
    print("Depth : $B1n");
    print("Nb : $C1n");
    print("Nb s : $C1 $C2n");
    print("Nk : $A1n");
    print("Nu : $A1/6n");
    print("Average number of comparisons is $C2/(7/6*$A1)n");
    $i  ;
}
print '--- END ---'."n";
  

Это основано на ответе xxFelixxxx

Ответ №1:

Внутри вашего while цикла вы вызываете @rows = <$fh>; , который будет принимать все строки вашего файла и помещать их в @rows . В следующий раз в цикле while он попытается сделать то же самое…но строк больше не осталось, поэтому @rows они будут пустыми. Поэтому, если вам нужны все строки, извлеките их за пределы вашего while цикла. Если вам нужно всего 2 строки за раз, вы можете просто захватить 2 строки внутри вашего цикла и проверить, что они не пустые:

 #!/usr/bin/env perl

use strict;
use warnings;

open my $fh, "<", "data.txt" or die "Unable to open data.txt for reading : $!";

while(1) {
    print '-'x50 . "n";
    my $line1 = <$fh>;
    last unless defined $line1;
    print "ODD  LINE $. : $line1";

    my $line2 = <$fh>;
    last unless defined $line2;
    print "EVEN LINE $. : $line2";
}
print '--- SUCCESS ---' . "n";
  

Вывод

 --------------------------------------------------
ODD  LINE 1 :   5000    5000    12497500    0
EVEN LINE 2 :   5000    5000    33258530    0
--------------------------------------------------
ODD  LINE 3 :   5000    13    51822    0
EVEN LINE 4 :   5000    13    130147    0
--------------------------------------------------
ODD  LINE 5 :   5000    28    75016    0
EVEN LINE 6 :   5000    28    181343    0
--------------------------------------------------
ODD  LINE 7 :   5000    5000    4999    4999
EVEN LINE 8 :   5000    5000    12580635    4999
--------------------------------------------------
--- SUCCESS ---
  

Обновить

В вашей обновленной версии у вас есть проблема с областью видимости, заключающаяся в том, что конструкция

 if (...) { 
    my ($foo) = 123;
}
print $foo; # <--- out of scope
  

означает, что остальная часть вашего кода не будет видеть переменные $A1,$B1,$C1,$D1 . Использование регулярных выражений не является необходимым и может быть более четко выражено с помощью a split для пробелов и a grep для цифр, для проверки работоспособности. Конструкция my @foo = ("abc","def","ghi"); более perlishly выражается как my @foo = qw( abc def ghi );

Вот обновленная версия:

 #!/usr/bin/env perl

use strict;
use warnings;

open my $fh, "<", "data.txt" or die "Unable to open data.txt for reading : $!";

my @types = qw(AL PL RL AA PA RA AB PB RB AR PR RR AS PS RS AV PV RV);

while(1) {
    print '-'x50 . "n";
    # TODO: better names than a,b,c,d
    my ($A1,$B1,$C1,$D1) = get_row($fh);
    last unless defined $A1;

    my ($A2,$B2,$C2,$D2) = get_row($fh);
    last unless defined $A2;

    my $type = shift @types; # Pull one off the front
    defined $type
        or die "No more types left!";

    my $Nb_plus_s = $C1   $C2;
    # sprintf("%0.2f", 123.456789) -> 123.46   # round to 2 decimals
    my $Nu = sprintf("%0.2f", $A1 / 6);
    my $avg_comparisons = sprintf("%0.2f", $C2/(7/6*$A1));

    print "For $typen";
    print "Node  : $A1n";
    print "Depth : $B1n";
    print "Nb    : $C1n";
    print "Nb s  : $Nb_plus_sn";
    print "Nk    : $A1n";
    print "Nu    : $Nun";
    print "Average number of comparisons is $avg_comparisonsn";
}
print '--- SUCCESS ---' . "n";

sub get_row {
    my ($file_handle) = @_;
    my $line = <$file_handle>;
    return unless defined $line;

    # Split on whitespace, keep only numbers
    my @data = grep {/d/} split /s /, $line;

    # Check that we have 4 columns of data
    (4 == scalar @data)
        or die "Cannot understand line: '$line'";

    return(@data);
}
  

Новый вывод

 --------------------------------------------------
For AL
Node  : 5000
Depth : 5000
Nb    : 12497500
Nb s  : 45756030
Nk    : 5000
Nu    : 833.33
Average number of comparisons is 5701.46
--------------------------------------------------
For PL
Node  : 5000
Depth : 13
Nb    : 51822
Nb s  : 181969
Nk    : 5000
Nu    : 833.33
Average number of comparisons is 22.31
--------------------------------------------------
For RL
Node  : 5000
Depth : 28
Nb    : 75016
Nb s  : 256359
Nk    : 5000
Nu    : 833.33
Average number of comparisons is 31.09
--------------------------------------------------
For AA
Node  : 5000
Depth : 5000
Nb    : 4999
Nb s  : 12585634
Nk    : 5000
Nu    : 833.33
Average number of comparisons is 2156.68
--------------------------------------------------
--- SUCCESS ---
  

Ответ №2:

$line1 и $line2 прочитайте первые две строки из файла. Проблема в цикле:

 @rows = <$fh>;
  

Это считывает все оставшиеся файлы в массив. В контексте списка, который накладывает назначение массива, вы всегда читаете все. Вы можете попробовать вместо

 while (! eof $fh) {
    my $line1 = <$fh>;
    push @rows, "Odd: $line1";
    last if eof $fh;

    my $line2 = <$fh>;
    push @rows, "Even: $line2";
}
print "@rows";
  

Он использует eof для определения конца ввода.