2016-10-11 5 views
2

Ich frage mich, warum kann ich nicht Ein Ausschnitt meines Codes in zwei Linien in Perl zu nehmen scheinen istWie zwei Zeilen aus einer Datei in Perl lesen

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

Dies ist die Art von Daten I haben in 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 

ich habe sah sich nach möglichen Lösungen, fand ich einige interessante Leads hier http://www.perlmonks.org/?node_id=620077, vor allem diese hier

my $fh = open("file"); 

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

und

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

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

    ... 
} 

Könnte ich auch fragen, was for =$fh->$line1,$line2 warum gibt es a = $ und warum es nicht funktioniert oder wie funktioniert es?

Jede Hilfe wird geschätzt!

Prost

UPDATE Okay, so könnte ich etwas fehlt, aber das ist die Operation I aus den Leitungen

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 : $A1\n"); 
    print("Depth : $B1\n"); 
    print("Nb : $C1\n"); 
    print("Nb+s : $C1+$C2\n"); 
    print("Nk : $A1\n"); 
    print("Nu : $A1/6\n"); 
    print("Average number of comparisons is $C2/(7/6*$A1)\n"); 
    $i++; 
} 
print '--- END ---'."\n"; 

Dies basiert auf xxFelixxxx Antwort

tun wollte
+0

Schon eine Weile her, seit ich Perl geschrieben habe, aber 'while (1) {' sieht aus wie eine Endlosschleife ohne Pause. Ich gehe davon aus, dass das beabsichtigt ist, aber nur für den Fall ... geht hoch. Wo wird '$ e' initialisiert? –

+1

'für = $ fh -> $ line1, $ line2' verwendet' perl6', was als eine andere, aber verwandte Sprache zu 'perl' aka' perl5' betrachtet werden sollte. – xxfelixxx

+0

Fügen Sie all Ihren Skripten 'use strict;' hinzu und beheben Sie alle Probleme, über die sie sich beschweren. Dies führt zu weniger fehlerhaftem Code. – xxfelixxx

Antwort

3

Innerhalb Ihrer while Schleife, rufen Sie @rows = <$fh>;, die alle Zeilen Ihrer Datei nehmen und sie in @rows. Das nächste Mal durch die while-Schleife wird es versuchen, das gleiche zu tun ... aber es sind keine weiteren Zeilen übrig, so @rows wird leer sein. Also, wenn Sie alle Zeilen benötigen, greifen Sie sie außerhalb Ihrer while Schleife. Wenn Sie nur zwei Zeilen zu einer Zeit benötigen, können Sie nur zwei Zeilen in Ihrer Schleife greifen und prüfen, ob sie nicht leer sind:

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

Ausgabe

-------------------------------------------------- 
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 --- 

aktualisieren

In Ihrer aktualisierten Version haben Sie ein Problem mit dem Gültigkeitsbereich, da das Konstrukt

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

bedeutet, dass der Rest Ihres Codes die Variablen $A1,$B1,$C1,$D1 nicht sehen wird. Die Verwendung von regulären Ausdrücken ist nicht notwendig und kann klarer ausgedrückt werden, indem split auf Whitespace und grep auf Ziffern zur Überprüfung der Integrität verwendet werden.Das Konstrukt von my @foo = ("abc","def","ghi"); mehr wird perlishly ausgedrückt als my @foo = qw(abc def ghi);

Hier ist eine aktualisierte Version:

#!/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 $type\n"; 
    print "Node : $A1\n"; 
    print "Depth : $B1\n"; 
    print "Nb : $C1\n"; 
    print "Nb+s : $Nb_plus_s\n"; 
    print "Nk : $A1\n"; 
    print "Nu : $Nu\n"; 
    print "Average number of comparisons is $avg_comparisons\n"; 
} 
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); 
} 

Neue Ausgabe

-------------------------------------------------- 
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 --- 
+0

Prost! Vielen Dank :) Das räumt viele Missverständnisse auf, die ich hatte! und ja, die Benennung war nicht einfach abcde, aber es waren Daten, die ich gerade bearbeitet habe, um die Dinge etwas einfacher zu machen :) – Pandaria

1

$line1 und $line2 die ersten beiden Zeilen aus der Datei gelesen. Problem ist in der Schleife:

@rows = <$fh>; 

Dies liest alle verbleibenden Dateien in das Array. Im Listenkontext, welche Array-Zuweisung erzwingt, lesen Sie immer alles. Sie können stattdessen versuchen

Es verwendet eof, um das Ende der Eingabe zu erkennen.

Verwandte Themen