Function 在Perl中找到我们想要的任何行号的最佳方法
例如,我正在阅读这个文件,在一些单词之后,我检查有多少“你”出现Function 在Perl中找到我们想要的任何行号的最佳方法,function,perl,Function,Perl,例如,我正在阅读这个文件,在一些单词之后,我检查有多少“你”出现 Good morning to you May every step you make you be filled you with happiness love you and peace you 我写的代码: use warnings; use strict; my $log1_file = "log.log"; my $you_count = 0; my $you_make_co
Good
morning
to
you
May
every
step
you
make
you
be
filled
you
with
happiness
love
you
and
peace
you
我写的代码:
use warnings;
use strict;
my $log1_file = "log.log";
my $you_count = 0;
my $you_make_count = 0;
my $you_love_count = 0;
my $point ;
open(IN1, "<$log1_file" ) or die "Could not open file $log1_file: $!";
while (my $line = <IN1>) {
$point =$.;
print "$. main while\n";
my @fields = split' ',$line;
if ($fields[0] eq "Good") {
print "$. after good_if\n";
good_check();
print "$. after good_call\n";
seek (IN1,$point,0);
#$. = $point;
print "$. \n";
}
elsif ($fields[0] eq "make") {
print "$. after make_if\n";
make_check();
#$. = $point;
seek (IN1,$point,0);
}
elsif ($fields[0] eq "love") {
print "$. after love_if\n";
love_check();
#$. = $point;
seek (IN1,$point,0);
}
}
print "$you_count\n";
print "$you_make_count\n";
print "$you_love_count\n";
close IN1;
sub love_check{
while (my $line = <IN1>)
my @fields = split' ',$line;
if ($fields[0] eq "you") {
$you_love_count++;
}
}
}
sub make_check{
while (my $line = <IN1>) {
my @fields = split' ',$line;
if ($fields[0] eq "you") {
$you_make_count++;
}
}
}
sub good_check{
while (my $line = <IN1>) {
my @fields = split' ',$line;
if ($fields[0] eq "you") {
$you_count++;
}
}
}
最终的“you”值是正确的,但没有得到正常的行号。
如果我使用$$点代码>只有第一个子系统工作正常
有谁能告诉我返回同一位置的最佳方法吗?文件是字节流。他们根本不懂台词。行结束字符只是流中的另一个字符
因此,当谈到“文件句柄的位置”时,它指的是通过文件的字节数,而不是行数。所以seek
ing到一个行号永远不会得到你想要的结果
相反,您应该使用查找文件中的位置,然后将该值用作发送到seek()
的参数
它的工作原理如下:
# Lexical filehandle and three-arg open()
open my $in_fh, '<', $log1_file or die ...;
my $pos = tell $in_fh;
while (my $line = <$in_fh>) {
# Do various stuff.
# If you want to go back to the start of the line.
seek $in_fh, $pos, 0;
# Get the pos at the end of the current line
$pos = tell $in_fh;
}
open my $fh, "<", $log1_file or die "Could not open '$log1_file': $!";
#词法文件句柄和三个参数open()
打开我的$in_fh,“这个问题看起来很像一个问题。或者做作业。计算与某些关键词相关的“你”的逻辑似乎是任意的。例如,“you”后面的“Good”将包含其他单词组合中的所有“you”
由于我假设这是某种学习练习,我将对您的代码进行注释,然后给出建议的解决方案
open(IN1, "<$log1_file" ) or die "Could not open file $log1_file: $!";
这种分裂是不必要的
my @fields = split' ',$line;
由于每行只有一个单词,因此只需删除末尾的换行符(因为在'
上拆分是一种特殊情况)。如果要删除换行符,应该使用chomp
,如下所示:chomp($line)
使用seek
和tell
浏览文件可能是错误的解决方案。虽然你可以让它工作,但有更好的解决方案
在我看来,使用三个几乎相同的子例程来做完全相同的事情(几乎)是不好的做法。在子例程中使用全局变量也不是一件好事。您应该寻求的是封装:将您需要的信息提供给子例程,然后返回您想要的值。例如:
my @file = <$fh> # slurp the file into an array
....
if (/^Good$/) {
$good_count += you_check($line_number);
} elsif (/^make$/) {
$make_count += you_check($line_number);
} ....etc
sub you_check {
my $line_number = shift;
my $count = 0;
for my $line ($file[$line_number] .. $file[$#file]) {
$count++ if $line =~ /^you$/;
}
return $count;
}
在命令行中这样使用它:
$ count.pl log.log
与示例数据一起使用时的输出为:
$VAR1 = {
'love' => 2,
'Good' => 2,
'make' => 2
};
如果您仍然希望保持第一个单词计数包含所有其他单词的规则,则可以跟踪哪个单词先出现,然后再添加计数。使用散列进行此计数可以扩展到您想要跟踪的任意多个单词。如果您想seek()
查找某个单词,请选中tell()
。你的计数逻辑是错误的。您的“良好”计数将是文件中所有的“您”,而“制造”将拥有所有,减去“良好”和“制造”之间的数字,等等。来回颠倒文件很少是正确的答案。你应该说出你想要完成什么,然后问是否有比这更好的解决方案。我很惊讶,也很头晕,有一个模块没有提到。威伊!
$ count.pl log.log
$VAR1 = {
'love' => 2,
'Good' => 2,
'make' => 2
};