1

我是一个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);
4

2 回答 2

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

希望这可以帮助!

于 2013-10-18T04:24:12.343 回答
1

正如Kenosis已经展示的那样,这最好用哈希来完成。但是,可以进行一些简化/改进。

  • 通过使用赋值=,我们每次都存储最新的值,因为相同的哈希键会相互覆盖。
  • 范围运算符..还可以增加字符串,这样我们就可以得到一个范围的字符串,比如00, 01, ... 59
  • defined-or 运算符//可以用作更简洁的方法来检查某个时间的键是否已定义。
  • 使用\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
于 2013-10-18T12:57:56.660 回答