2

不完全确定为什么,但由于某种原因,我无法在 while 循环之外打印散列值。

#!/usr/bin/perl -w

opendir(D, "cwd" );
my @files = readdir(D);
closedir(D); 

foreach $file (@files)
{
        open F, $file or die "$0: Can't open $file : $!\n";
        while ($line = <F>) {
                chomp($line);
                $line=~ s/[-':!?,;".()]//g;
                $line=~ s/^[a-z]/\U/g;
                        @words = split(/\s/, $line);
                        foreach  $word (@words) {
                                 $frequency{$word}++;
                                $counter++;
                }

        } 
         close(F);

        print "$file\n";
        print "$ARGV[0]\n";
        print "$frequency{$ARGV[0]}\n";
        print "$counter\n";
}

任何帮助将非常感激!干杯。

4

2 回答 2

1

这条线

print "$frequency{$ARGV[0]}\n";

期望您对脚本有一个参数,例如perl script.pl argument. 如果您没有参数,$ARGV[0]则未定义,但它将字符串化为空字符串。此空字符串是哈希中的有效键,但该值未定义,因此您的警告

Use of uninitialized value within %frequency in concatenation (.) or string

但你也应该看到警告

Use of uninitialized value $ARGV[0] in hash element

在这个问题中不包括这个错误是一个很大的错误。

此外,使用 时readdir,您将获得目录中的所有文件,包括目录。您可能会考虑对文件进行一些过滤。

使用

use strict;
use warnings;

是什么对你很有好处,所以把它添加到你的脚本中。

于 2013-09-16T14:44:58.910 回答
0

原来是这样写的

%frequency在您的程序的顶层没有定义。

perl看到你%frequency在最里面的循环中引用时,它会在那个暂存器(词法范围)中自动激活它。

这意味着当您退出最内层循环 ( foreach $word (@words)) 时,自动激活的对象%frequency将超出范围并被垃圾收集。每次进入该循环时, 都会自动激活一个新的不同变量,然后将其丢弃。

当您稍后%frequency在您的 中引用时,将创建print另一个新的、不同的。%frequency

…但后来意识到你忘记了use strict,Perl 很慷慨,给你一个global %frequency,讽刺的是,这可能就是你的意思。因此,在您的情况下,这个答案是错误的……但无论如何,声明范围%frequency可能是一种好的形式。

这些其他“不相关”的注释也许仍然有用,否则我会完全删除答案:


正如@TLP 提到的,您可能还应该(至少)在文件循环中跳过目录。一个快速的方法是my @files = grep { -f "cwd/$_" } (readdir D);这将过滤列表以仅包含文件。

我更怀疑您命名了一个目录"cwd"……您可能是指当前的工作目录吗?在当今使用的所有主要操作系统中,该目录都被称为“<code>”。— 您正在寻找一个字面上名为"cwd"?

于 2013-09-16T17:53:45.270 回答