计算文件中字符串的出现次数

时间:2012-08-15 22:23:24

标签: perl

我编写了一个perl脚本来计算文件中字符的出现次数。 到目前为止,这就是我所拥有的,

#!/usr/bin/perl -w

use warnings;
no warnings ('uninitialized', 'substr');

my $lines_ref;
my @lines;
my $count;

sub countModule()
{
my $file = "/test";
open my $fh, "<",$file or die "could not open $file: $!";
my @contents = $fh;
my @filtered = grep (/\// ,@contents);
return \@filtered;
}

@lines = countModule();
#@lines = $lines_ref;
$count = @lines;
print "###########\n $count \n###########\n";

我的测试文件如下所示:

10.0.0.1/24
192.168.10.0/24
172.16.30.1/24

我基本上试图计算“/”

的实例数

这是我得到的输出:

###########
 1
###########

我得到1而不是3,这是出现次数。 还在学习perl,所以任何帮助都会受到赞赏。谢谢!!

4 个答案:

答案 0 :(得分:1)

关闭,但有几个问题:

use strict;
use warnings;

sub countModule
{
    my $file = "/test";
    open my $fh, "<",$file or die "could not open $file: $!";
    my @contents = <$fh>;  # The <> brackets are used to read from $fh.
    my @filtered = grep (/\// ,@contents);
    return @filtered;      # Remove the reference.
}

my @lines = countModule();
my $count = scalar @lines;  # 'scalar' is not required, but lends clarity.
print "###########\n $count \n###########\n";

我对您的代码所做的每项更改都使用#comment进行了注释,以解释已完成的操作。

现在在列表上下文中,子例程将返回已过滤的行。在标量上下文中,它将返回过滤了多少行的计数。

您还提到了查找字符的出现(尽管您的脚本中的所有内容都是面向行的)。也许你的反击子看起来像这样:

sub file_tallies{
    my $file = '/test';
    open my $fh, '<', $file or die $!;
    my $count;
    my $lines;
    while( <$fh> ) {
        $lines++;
        $count += $_ =~ tr[\/][\/];
    }
    return ( $lines, $count );
}

my( $line_count, $slash_count ) = file_tallies();

答案 1 :(得分:1)

以下是关于您的代码的几点

  • 您应该始终 use strict位于程序的顶部,并且仅在有限范围内因特殊原因使用no warnings。工作的Perl程序应该需要全局禁用警告

  • 声明您的变量接近其第一个使用点。在文件顶部声明所有内容的样式是不必要的,并且是C

  • 的遗产
  • 从不在代码中使用原型。它们可用于非常特殊的目的,不应用于绝大多数Perl代码。 sub countModule() { ... }坚持countModule可能永远不会使用任何参数调用,并且不是必需或有用的。定义应该只是sub countModule { ... }

  • 一个很好的做得好!使用词法文件句柄,三参数形式的open,并将$!放入你的死亡字符串

  • my @contents = $fh只会将@contents设置为仅包含文件句柄的单个元素列表。要将整个文件读入数组,您需要my @contents = <$fh>

  • 如果使用不同的分隔符,则可以避免在正则表达式中转义斜杠。为此,您需要明确使用m运算符,例如my @filtered = grep m|/|, @contents)

  • 返回数组引用但将返回的值赋给数组,因此@lines = countModule()@lines设置为仅包含数组引用的单元素列表。您应该返回包含return @filtered的列表,或者使用@lines = @{ countModule }取消引用返回值

如果您只需要打印文件中包含斜杠字符的行数,那么您可以编写类似这样的内容

use strict;
use warnings;

my $count;

sub countModule {
  open my $fh, '<', '/test' or die "Could not open $file: $!";
  return [ grep m|/|, <$fh> ];
}

my $lines = countModule;
$count = @$lines;
print "###########\n $count \n###########\n";

答案 2 :(得分:0)

在列表上下文中,

return \@filtered;

返回一个包含一个元素的列表 - 对指定数组@filtered的引用。也许你想要自己返回列表

return @filtered;

答案 3 :(得分:-1)

这是一些更简单的代码:

sub countMatches {
    my ($file, $c) = @_;   # Pass parameters
    local $/;
    undef $/; # Slurp input
    open my $fh, "<",$file or die "could not open $file: $!";
    my $s = <$fh>;  # The <> brackets are used to read from $fh.
    close $fh;
    my $ptn = quotemeta($c);  # So we can match strings like ".*" verbatim
    my @hits = $s =~ m/($ptn)/g;
    0 + @hits
}

print countMatches ("/test", '/') . "\n";

代码推动Perl超越了基础,但不是太多。突出点:

  1. 通过取消$ /,您可以将输入读入一个字符串。如果你在数数 在文件中出现字符串,而不是出现包含的行 字符串,通常更容易做到。

  2. m /(...)/ g会找到所有的点击数,但是如果你想计算字符串就像 “”你需要在其中引用元字符。

  3. 将结果存储在数组中以评估列表上下文中的m //

  4. 将0添加到列表中会显示其中的项目数。