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