【问题标题】:Perl - Use of uninitialized value within %frequency in concatenation (.) or stringPerl - 在连接(。)或字符串中使用%频率内的未初始化值
【发布时间】:2013-09-17 01:53:45
【问题描述】:

不完全确定为什么,但由于某种原因,我无法在 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";
}

任何帮助将不胜感激! 干杯。

【问题讨论】:

  • 如何调用脚本? perl the-script.pl someWord? $ARGV[0] 要求输入第一个命令行参数。除此之外,您可能希望将该脚本重写为use strict 等。它也应该很快死掉,当它想将父目录.. 作为文件打开时。您需要检查该文件是否为普通文件,例如next unless -f $file.
  • 总是:use strict; use warnings;。在循环外声明%frequency
  • @M42 %frequency 没有声明为词法,而且他没有使用严格,所以这不是问题。

标签: perl hash initialization


【解决方案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;

对你有很大帮助的东西,所以把它添加到你的脚本中。

【讨论】:

    【解决方案2】:

    这是我最初写的,

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

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

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

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

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

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


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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-04
      • 2014-05-20
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      相关资源
      最近更新 更多