多文件的Perl字数

时间:2015-11-04 16:11:38

标签: perl

我必须显示字符,单词和行的计数,然后将它们总计在格式化的printf的底部。不知何故,当我输入两个要计数的文件时,它只打印出一个计数。此外,我似乎只是将计数添加到一起,它应该为每个文件显示一个单独的计数,然后在最后将它们一起添加。我正在从命令控制台输入文件,所以它会 perl mywc.pl

这就是我所拥有的,我确定我在循环中遗漏了一些内容,但我无法弄清楚是什么。

#!usr/bin/perl
use warnings;
use strict;

my $text_lines = 0;
my $words = 0;
my $chars = 0;
my $counter = 0;
my $total_word = 0;
my $total_char = 0;
my $total_line = 0;

printf ("%-15s", "Files");
printf ("%15s", "Characters");
printf ("%15s", "Words");
printf ("%15s", "Lines\n");

while ($counter < scalar(@ARGV))
{

    open(INPUT, '<', $ARGV[$counter]) or die "Cannot open file!";
    my @doc = <INPUT>;
    foreach my $lines (@doc)
    {
        $text_lines++;
        $chars += length ($lines);
        $words += scalar(split(/\s+/, $lines)); 
    }

    printf ("%-15s", "$ARGV[$counter]");
    printf ("%15s", "$chars");
    printf ("%15s", "$words");
    printf ("%15s", "$text_lines\n");

    $total_word += $words;
    $total_char += $chars;
    $total_line += $text_lines;  
    close INPUT;
    $counter++;
}

printf ("%-15s", "TOTAL");
printf ("%15s", "$total_char");
printf ("%15s", "$total_word");
printf ("%15s", "$total_line\n");

#print "Characters: $chars\n";
#print "Words: $words\n";
#print "Lines: $text_lines\n";

3 个答案:

答案 0 :(得分:2)

  

不知何故,当我输入两个要计数的文件时,它只打印出一个计数。

那不是真的。

$ script .bashrc .bash_profile
Files               Characters          Words         Lines
.bashrc                   2146            317            89
.bash_profile             3339            502           148
TOTAL                     5485            819           237

(不得不修复shebang路径,因为它需要是绝对路径。)

  

我确定我在循环中遗漏了一些内容,但我无法弄清楚是什么。

然而,这是真的。您的结果不正确。正确的计数如下:

$ wc .bashrc .bash_profile
  89  289 2146 .bashrc
  59  174 1193 .bash_profile
 148  463 3339 total

您会注意到第一个文件的行数和字符数是正确的,但第二个文件的行数和字符数不正确。这是因为您忘记重置每个文件的计数。

(忽略这些词,因为可能会使用&#34; word&#34;的不同定义。)

将以下行移动到外部循环中,因为它们仅适用于正在检查的文件:

my $text_lines = 0;
my $words = 0;
my $chars = 0;

答案 1 :(得分:0)

我相信你想要计算通过命令行传递的每个文件中的字符,单词和行号。

但是代码的问题是你在全局声明所有变量,只有总计数变量必须是全局的,因为在处理完所有文件后你需要它们。其他变量应该在处理每个文件之前在本地声明它处理完每个文件后应该超出范围,并在下一个文件上重新初始化。

第二件事my @doc = <INPUT>这里你把整个文件都记在内存中,这根本不需要。

我将如下所示:

#!/usr/bin/perl
use strict;
use warnings; 

print "No files provided\n" unless(@ARGV);

my ($total_word,$total_char,$total_line)=(0,0,0);
printf ("%-15s", "Files");
printf ("%15s", "Characters");
printf ("%15s", "Words");
printf ("%15s", "Lines\n");

foreach my $file (@ARGV){
       open my $fh, '<', $file or die "unable to open file $file: $!\n";
       #Declare variables separately here for each file
       my($words,$chars,$lines)=(0,0,0); 
       while(my $line=<$fh>){
         $lines++;
         $chars += length ($line);
         $words += scalar(split(/\s+/, $line));
       }
       printf ("%-15s", $file);
       printf ("%15s", $chars);
       printf ("%15s", $words);
       printf ("%15s", "$lines\n");

       $total_word += $words;
       $total_char += $chars;
       $total_line += $lines;

       close $fh;
}
printf ("%-15s", "TOTAL");
printf ("%15s", "$total_char");
printf ("%15s", "$total_word");
printf ("%15s", "$total_line\n");

答案 2 :(得分:0)

我会使用Perl的while (<>) { ... }构造以及$ARGV变量。

#!/usr/bin/perl

use strict;
use warnings;

print "No files provided\n" unless(@ARGV);

my ($total_word,$total_char,$total_line)=(0,0,0);
printf ("%-15s", "Files");
printf ("%15s", "Characters");
printf ("%15s", "Words");
printf ("%15s", "Lines\n");

my %file_counts;
my @files = @ARGV; # Take a copy

while (<>) {
    $file_counts{$ARGV}{lines}++;
    $file_counts{$ARGV}{chars} += length;
    $file_counts{$ARGV}{words} += split;
}

foreach (@files) {
    printf ("%-15s", $_);
    printf ("%15s", $file_counts{$_}{chars});
    printf ("%15s", $file_counts{$_}{words});
    printf ("%15s", "$file_counts{$_}{lines}\n");

    $total_char += $file_counts{$_}{chars};
    $total_word += $file_counts{$_}{words};
    $total_line += $file_counts{$_}{lines};
}

printf ("%-15s", "TOTAL");
printf ("%15s", "$total_char");
printf ("%15s", "$total_word");
printf ("%15s", "$total_line\n");