【问题标题】:How to read two lines from a file in perlperl如何从文件中读取两行
【发布时间】:2016-10-12 00:09:13
【问题描述】:

我想知道为什么我似乎无法在 Perl 中接受 2 行 我的代码的 sn-p 是

#!/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-&gt;$line1,$line2 为什么会有 =$ 以及为什么它不起作用或它是如何起作用的?

感谢任何帮助!

干杯

更新 好吧,所以我可能遗漏了一些东西,但这是我想从线条上做的操作

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 的回复

【问题讨论】:

  • 自从我编写 perl 以来已经有一段时间了,但 while(1){ 看起来像一个没有中断的无限循环。我假设这是故意的,但以防万一......抬头。另外,$e 在哪里初始化?
  • for =$fh-&gt;$line1,$line2 正在使用 perl6,这应该被视为与 perl 又名 perl5 不同但相关的语言。
  • use strict; 添加到您的所有脚本中,并修复它抱怨的所有问题,这将减少错误代码。
  • 是的 while(1) 是故意的,很抱歉 $e 在顶部被初始化但我错误地把它取出来了。 @ParthianShot
  • 啊,我看到了关于 for =$... 但可以在 perl5 中做到这一点吗? - nvm 在底部看到你的答案对不起!@xxfelixxx

标签: perl


【解决方案1】:

while 循环中,您调用@rows = &lt;$fh&gt;;,它将获取文件的所有行并将它们放入@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"); 的构造更糟糕地表示为 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 ---

【讨论】:

  • 干杯!非常感谢:)这消除了我的很多误解!是的,命名不仅仅是 abcde,而是我刚刚决定编辑的数据以使事情变得更容易:)
【解决方案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 来检测输入的结束。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 2021-02-01
    • 2014-07-25
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多