Perl中文件的字和行数以及字节大小

时间:2013-11-08 08:04:22

标签: perl filesize word-count

我正在尝试编写一个Perl程序,它从命令行获取一个文件,计算行数(工作正常),以字节为单位显示文件大小(仅在我工作时才有效)将print语句放在while循环中,但是打印出我认为的行的大小,因为它的每个循环不同),单词的总数,并计算特定搜索单词的出现次数命令行。

如何让它按预期工作?

#!/usr/bin/perl

use strict;
use warnings;

my $linecount = 0;
my $wordcount = 0;
my $filesize = 0;
my $search = <>;

while (defined(my $file = <>)) {
    chomp($file);

    my $filesize = length $file;

    if (m/$search/){
        my $wordcount++;
    }

    $linecount = 1;
    $linecount++;
}

print "Size of file in bytes: $filesize\n";
print "Number of line(s): $linecount\n";
print "Number of occurences of $search: $wordcount\n";

3 个答案:

答案 0 :(得分:1)

  

我正在使用./perl1.pl testfile.txt你好。您好,我的搜索词

<>读取告诉perl读取命令行中所有文件中的行(或来自STDIN的行)。

由于cmd行中的参数存储在@ARGV中,并且hello不是您示例中的文件,因此应将其删除并存储在其他位置(my $search = pop @ARGV;

use strict;
use warnings;

my $linecount = 0;
my $wordcount = 0;
my $search = pop @ARGV;
my ($file) = @ARGV;
my $filesize = -s $file;

while (my $line = <>) {
    chomp($line);

    $wordcount++ while $line =~ /$search/g;

    $linecount++;
}

print "Size of file in bytes: $filesize\n";
print "Number of line(s): $linecount\n";
print "Number of occurrences of $search: $wordcount\n";

答案 1 :(得分:1)

快速代码审核:

use strict;
use warnings;

一个非常好的选择。这些编译指示提供有关代码的信息,并帮助您避免错误。

my $search = <>;

在这里,您将输入的第一行作为搜索字符串。这可能不是你想要的。如果您正在搜索文件,我猜测该文件不包含第一行中的搜索词。您可能要做的是访问命令行参数,这些参数位于@ARGV

my $search = shift;  

这是访问@ARGV的惯用方式。它是shift @ARGV的缩写,它将第一个参数关闭@ARGV

while (defined(my $file = <>)) {
    chomp($file);
    my $filesize = length $file;

我的印象是您认为$file实际上是文件名。你说你试过-s $file,如果$file包含了文件名,那就可以了。但是,while循环从输入文件句柄<>读取并将文件行分配给$file。如果要访问文件 name ,您可能需要$ARGV。你只想做一次, while循环之后:

my $filesize = -s $ARGV;

请注意,如果您使用多个文件,$ARGV会更改,因为它引用当前正在使用<>读取的文件的名称。 (技术上<ARGV>

while循环本身应该使用不同的变量名:

while (my $line = <>)

请注意,您在技术上不需要在此处使用defined

此外,length返回字符串中的字符数。如果在文件名上使用它,则返回文件名中的字符数。它与文件大小无关。

if (m/$search/){
    my $wordcount++;
}

此模式匹配适用于默认变量$_。你想要的是$file =~ m/..../。此外,您是否希望元字符在正则表达式中处于活动状态?例如,您可能希望允许使用s复数/apples?/。但是,元字符可以更改模式匹配的含义,因此,如果您只想匹配文字字符串,请使用\Q ... \E转义来禁用元字符。

另一件事,你在这里使用my来声明一个新变量(它隐藏了先前声明的变量)。此变量仅具有周围if块的范围,因此它毫无意义。删除my

另一件事是这个匹配每行只匹配一次,所以你错过了多场比赛。你想要的可能就是:

$wordcount += () = $line =~ /\Q$search\E/g;

请注意使用全局/g修饰符,使正则表达式尽可能多次匹配(而不仅仅是一次)。在标量上下文中使用()返回模式匹配中的匹配数。

$linecount = 1;
$linecount++;

这会将计数设置为2.无论文件中有多少行,这都不会超过2.您想要删除作业。

答案 2 :(得分:0)

你知道Perl中的模式匹配是如何工作的吗?这就是我要做的事情:

foreach $match ($line =~ /\w+/gi)
{
  chomp($match);

  if($match eq $search)
  {
     $wordcount++;
  }
}

我用“$ line”替换了“$ file”,因为它有点令人困惑。我猜你的情况并不是真的有必要,因为你之前已经完成了。模式[\ w] +将从行中搜索一个或多个“单词”字符的序列,并将结果匹配存储在$ match中。 =〜运算符的作用是使它连续移动$ line变量,将它找到的单词存储到$ match中。匹配上的“g”标志是全局的,这意味着它将搜索整行。以下“i”用于不区分大小写的搜索(如果需要,可以删除它)。然后,如果匹配与我们的搜索变量相同,我们增加wordcount。