#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 для определения конца ввода.