Perl - while循环不起作用

时间:2013-10-18 02:11:53

标签: perl

我是一名perl新秀,不知道怎么做......

我的输入文件:

random text 00:02 23
random text 00:04 25
random text 00:06 53
random text 00:07 56
random text 00:12 34
 ... etc until 23:59

我想得到以下输出:

00:00
00:01
00:02 23
00:03
00:04
00:05
00:06 53
00:07 56
00:08
00:09
00:10
00:11
00:12 34
... etc until 23:59

因此输出文件具有每分钟时间戳和输入文件中找到的相应值。我的输入文件从00:00开始,到23:59结束

我的代码是:

 use warnings;
 use strict;

 my $found;
 my @event;
 my $count2;

 open (FILE, '<./input/input.txt');
 open (OUTPUT, '>./output/output.txt');


    while (<FILE>){
           for ($count2=0; $count2<60; $count2++){

                my($line) = $_;

                if($line =~ m|.*(00:$count2).*|){
                $found = "$1 \n";
                push @event, $found;     
                }

                if (@event){
                }
                else {                                                      
                    $found2 = "00:$count2,";
                    push @event, $found2;   

                }         
                }                    
                }
                print OUTPUT (@event);

               close (FILE);
               close (OUTPUT);

2 个答案:

答案 0 :(得分:4)

这是您的任务的一种方法:

use strict;
use warnings;

my %hash;

open my $inFH, '<', './input/input.txt' or die $!;

while (<$inFH>) {
    my ( $hr_min, $sec ) = /(\d\d:\d\d)\s+(.+)$/;
    push @{ $hash{$hr_min} }, $sec;
}

close $inFH;

open my $outFH, '>', './output/output.txt' or die $!;

for my $hr ( 0 .. 23 ) {
    for my $min ( 0 .. 59 ) {
        my $hr_min = sprintf "%02d:%02d", $hr, $min;
        my $sec = defined $hash{$hr_min} ? " ${ $hash{$hr_min} }[-1]" : '';
        print $outFH "$hr_min$sec\n";
    }
}

close $outFH;

第一部分读取输入文件并使用正则表达式来获取每个字符串末尾的时间。构建了一个数组哈希(HoA),其中HH:MM作为键和数组中的秒。例如:

09:14 => ['21','45']

这意味着在09:14有两个第二次进入:一次是21秒,另一次是45秒。由于输入文件中的时间是按升序排列的,因此可以使用[-1]下标获得数组中的最高值。

接下来,设置两个循环:外部是(0..23),内部是(0..59),sprintf用于格式化HH:MM。当在对应于循环中的当前HH:MM的散列中找到键时,HH:MM和阵列中的最后一项(最大秒数)被打印到文件(例如,00:02 23)。如果哈希中没有相应的HH:MM,则只打印循环的HH:MM(例如,00:03):

示例输出:

00:00
00:01
00:02 23
00:03
00:04 45
00:05
00:06 53
00:07 59
00:08
00:09
00:10
00:11
00:12 34
...
23:59

希望这有帮助!

答案 1 :(得分:1)

最好使用哈希,Kenosis已经显示。但是,可以进行一些简化/改进。

  • 通过使用赋值=,我们每次都存储最新值,因为相同的哈希键会相互覆盖。
  • 范围运算符..也可以增加字符串,以便我们可以获得一系列字符串,例如0001,... 59
  • 定义的或运算符//可以用作更简洁的方法来检查是否定义了特定时间的密钥。
  • 使用\d+而不是.+会更加安全,因为它会阻止hindsight is 20:20 at 01:23 45之类的内容错误地匹配20:20
  • 我们不使用硬编码文件名,而是使用shell重定向和参数。

在下面的示例代码中,我使用较小范围的数字进行演示。我还使用了DATA文件句柄,以便可以复制/粘贴此代码并进行尝试。要试用它,请将<DATA>更改为<>并按以下方式运行:

perl script.pl input.txt > output.txt

<强>代码:

use strict;
use warnings;
use feature 'say';

my %t;
while (<DATA>) {
    if (/((\d{2}:\d{2})\s+\d+)$/) {
        $t{$2} = $1;             # store most recent value
    }
}
for my $h ('00' .. '00') {          
    for my $m ('00' .. '12') {      
        my $time = "$h:$m";
        say $t{$time} // $time;  # say defined $t{$time} ? $t{$time} : $time;
    }
}
__DATA__
random text 00:02 23
random text 00:04 25
random text 00:06 53
random text 00:07 56
random text 00:12 34
random text 00:12 39

<强>输出:

00:00
00:01
00:02 23
00:03
00:04 25
00:05
00:06 53
00:07 56
00:08
00:09
00:10
00:11
00:12 39