如何在perl中循环浏览文件并计算特定值?

问题描述 投票:0回答:1

假设我有一个文件,其中的行数如下。

*some numbers* :00: *somenumbers*
*somenumbers* :21: *somenumbers*

对于每一个介于 :: 我需要计算它在文件中重复了多少次?

while (<>){     
    chomp($_);
    my ($nebitno,$bitno,$opetnebitno) = split /:/, $_;
    $count{$bitno}++;
}
foreach $bitno(sort keys %count){
    print $bitno," ",$count{bitno}, "\n";
}
file perl
1个回答
2
投票

你生成的代码并不差--它一次只完成了一个文件的工作。将问题中所示的代码改编为处理多个文件,在每个文件之后重置计数。

#!/usr/bin/perl

use strict;
use warnings;

my %count = ();

while (<>) {     
    my ($nebitno, $bitno, $opetnebitno) = split /:/, $_;
    $count{$bitno}++;
}
continue
{
    if (eof) {
        print "$ARGV:\n";
        foreach $bitno (sort keys %count) {
            print "$bitno $count{bitno}\n";
        }
        %count = ();
    }
}

这里的关键是... continue 块,而 if (eof) 测试。 您可以使用 close $ARGV 在继续块中重置 $. (行号),当文件发生变化时,它是一种常见的用法。 这种每个文件的摘要是另一种用法。 其他的变化都是表面上的。 你不需要咬住行号(虽然这样做并没有什么特别的坏处);我打印整个字符串,而不是使用逗号分隔的列表(它在这里很好用,而且很常见)。 我多用了几个空格。 我给代码块留了1TBS格式,虽然我自己不用这个格式(我用Allman)。

我的解决方案草案几乎使用了与上图相同的打印代码,但主要的 while 循环略有不同。

#!/usr/bin/env perl

use strict;
use warnings;

my %counts = ();

while (<>)
{
    $counts{$1}++ if (m/.*:(\d+):/);
}
continue
{
    if (eof)
    {
        print "$ARGV:\n";
        foreach my $number (sort { $a <=> $b } keys %counts)
        {
            print ":$number: $counts{$number}\n"
        }
        %counts = ();
    }
}

唯一的优点是如果某行没有冒号包围的数字,它就会忽略这行,而你的循环没有考虑这种可能性。 我不知道你的比较代码中的 sort 是有必要的--虽然它能确保比较的是数字。 如果数字的长度都是一样的,而且在必要的时候在左边加零垫,就没有问题。 如果它们的格式比较一般,"强制数字 "比较可能会有所区别。

记住:这是Perl,所以TMTOWDTI(There's More Than One Way To Do It)。 别人可能会提出一个更简单的解决方案。


-2
投票

以下代码可以达到预期的输出效果

  • 找规律 :\d+: 一字排开
  • 增量哈希 %count 对于数字
  • 输出结果
use strict;
use warnings;
use feature 'say';

my %count;

/:(\d+):/ && $count{$1}++ for <>;

say "$_ = $count{$_}" for sort keys %count;

© www.soinside.com 2019 - 2024. All rights reserved.