2016-10-11 141 views
2

我很奇怪,爲什麼我似乎無法採取2號線在Perl 我的代碼片段是如何讀取在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]"; 
} 

這是一種數據I在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爲什麼會有= $爲什麼它不工作或者它是如何工作的?

任何幫助表示讚賞!

乾杯

UPDATE 好了,所以我可能會丟失的東西,但是這是我想從線

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

做手術這是基於xxFelixxxx的迴應

+0

自從我寫了perl之後過去了一段時間,但'while(1){'看起來像一個無休止的無限循環。我假設這是故意的,但以防萬一...擡起頭來。另外,$ e初始化在哪裏? –

+1

'for = $ fh - > $ line1,$ line2'正在使用'perl6',這應該被認爲是不同的,但相關的語言是'perl'又名'perl5'。 – xxfelixxx

+0

將'strict strict;'添加到所有腳本中,並修復它所抱怨的所有問題,這將導致更少的錯誤代碼。 – xxfelixxx

回答

3

在您的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。使用正則表達式不是必需的,可以使用空格上的split和數字上的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 $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); 
} 

新建輸出

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

乾杯!非常感謝:)這清除了我的很多誤解!是的命名不只是abcde,但它是一個數據,我只是決定編輯,使事情變得更容易:) – Pandaria

1

$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來檢測輸入的結束。