【问题标题】:How to loop through file and count specific values in perl?如何遍历文件并计算perl中的特定值?
【发布时间】:2020-04-28 03:24:45
【问题描述】:

假设我有一个文件,其中包含以下行:

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

【问题讨论】:

  • (a) 你试过什么? (b) 冒号是不是只有这些地方出现在一行上?一行可以有多个:\d+: 序列吗? (c) 如果您在命令行中指定了多个文件,您是要对每个文件进行计数,还是对这些文件进行汇总?
  • (a) 我是 perl 新手,曾尝试将值放入列表中,然后增加了一些计数器,但看起来一点希望都没有 (b) 是的,这些是冒号出现在一行中的唯一位置只有一个::序列(c)我想为每个文件计数
  • 我再说一遍:你试过什么?给我们看一看!有很多方法可以做到这一点——这是 Perl,所以是 TMTOWDTI(有不止一种方法可以做到)。你试过什么?您可能应该使用由数字字符串索引的哈希;你可以使用一个普通的数组。数字是否总是两位数,或者它们可以更大,更小?消极的?有一个积极的迹象?如果是肯定的,10+10 算作 1 个或 2 个不同的数字吗?
  • 这里没有考虑可以指定多个文件
  • 好的;除了不处理多个文件以及没有use strict;use warnings; 之外,这是一份体面的工作。 (始终使用两组 use,至少在您编写 Perl 的时间比我长(1992 年,或者可能更早一点)之前——我不相信我的脚本,直到它们对那些 use 干净为止选项;我不是一个优秀的 Perl 程序员。

标签: file perl


【解决方案1】:

您生成的代码还不错——它一次只处理一个文件。调整问题中显示的代码以处理多个文件,在每个文件之后重置计数:

#!/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) 测试。您可以在 continue 块中使用 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(有不止一种方法可以做到)。其他人可能会想出一个更简单的解决方案。

【讨论】:

    【解决方案2】:

    可以使用以下代码sn-p实现所需的输出

    • 在一行中寻找模式:\d+:
    • 为数字增加哈希%count
    • 输出结果到控制台
    use strict;
    use warnings;
    use feature 'say';
    
    my %count;
    
    /:(\d+):/ && $count{$1}++ for <>;
    
    say "$_ = $count{$_}" for sort keys %count;
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-22
      • 2021-12-01
      • 2022-11-12
      • 2010-10-30
      • 2021-08-04
      • 1970-01-01
      相关资源
      最近更新 更多