我正在尝试编写一个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";
答案 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。