2

所以我试图用下面的代码做的是推一个字符串,让我们说“这个字符串”到散列中每个键的末尾。我完全不知道如何做到这一点。这是我的代码:

use warnings;
use strict;
use File::Find;

my @name;
my $filename;
my $line;
my @severity = ();
my @files;
my @info = ();
my $key;
my %hoa;
my $xmlfile;
my $comment;
my @comments;

open( OUTPUT, "> $ARGV[0]" );
my $dir = 'c:/programs/TEST/Test';

while ( defined( $input = glob( $dir . "\\*.txt" ) ) ) {
    open( INPUT, "< $input" );

    while (<INPUT>) {
        chomp;

        if (/File/) {
            my @line = split /:/;
            $key = $line[1];
            push @{ $hoa{$key} }, "Filename\n";
        }

        if ( /XML/ ... /File/ ) {
            $xmlfile = $1;
            push @{ $hoa{$key} }, "XML file is $xmlfile\n";

        }
        if (/Important/) {
            push @{ $hoa{$key} }, "Severity is $_\n";
        }
        if (/^\D/) {
            next if /Important/;
            push @{ $hoa{$key} }, "Given comment is $_\n";
        }
        push @{ $hoa{$key} }, "this string\n";
    }

}

foreach my $k ( keys %hoa ) {
    my @list = @{ $hoa{$k} };
    foreach my $l (@list) {
        print OUTPUT $l, "\n";
    }
}

}
close INPUT;
close OUTPUT;

我有“这个字符串”的地方是我试图将该字符串推到数组末尾的地方。然而,最终发生的是它最终打印了三遍“这个字符串”,而不是像我想要的那样在每个键的末尾。当我试图把它放在 while() 循环之外时,它说 $key 的值没有被初始化。所以请,有什么帮助吗?如果您需要澄清我的问题,请告诉我。谢谢!

4

5 回答 5

3

没有冒犯,但是这段代码中有很多问题我什至不知道从哪里开始......

my $something; my @somethings首先, Perl 中不需要“初始化块”(脚本开头的所有这些行)。事实上,这不仅仅是“冗余”——它实际上是令人困惑的:每次我遇到一个新变量时,我都必须来回移动我的注意力来检查它的类型。此外,即使有了所有这些$inputvar 仍然没有声明为本地;它要么在注释中丢失,要么给出的代码有遗漏。

其次,你为什么声明你打算使用 File::Find(好)——但是根本不使用它?它可以大大简化所有这些while(glob) { while(<FH>) { ... } }程序。

第三,我不确定为什么$key只有在读取的行与 /File/ 匹配时才分配某些东西 - 但在所有其他情况下使用它的值作为键。这是尝试读取按部分组织的文件吗?然后可以通过 slurp/splitting 或本地化$/变量来完成更简单的操作...

无论如何,关键是如果扫描文件的第一行与 不匹配/File/,则使用前一个(即,来自前一个文件!)值 - 我不太确定它的意图。如果第一个文件的第一行不/File/匹配,则使用空字符串作为键 - 再次,它闻起来像一个错误......

您能否更详细地描述您的任务?给出一些测试输入/输出结果,也许......在短期任务中继续进行,在过程中组织你的代码会很棒。

于 2012-07-20T13:47:51.717 回答
3

您的程序构思不周,违反了许多良好的实践规则。这里没有一一列举,而是一个结构更好的等效程序。

我想知道您是否知道所有语句都将if被测试并可能执行?也许您需要使用elsif?

除了 $key 在使用时未定义的可能性之外,您还设置$xmlfile$1永远不会定义的选项,因为在您的任何正则表达式中都没有捕获。

不可能从您的代码中看出您正在尝试做什么,因此只有在您向我们展示您的输出、输入并说明如何从另一个中推导出一个时,我们才能为您提供帮助。

use strict;
use warnings;

use File::Find;

my ($outfile) = @ARGV;

my $dir = 'c:/programs/TEST/Test';

my %hoa;
my $key;

while (my $input = glob "$dir/*.txt") {

  open my $in, '<', $input or die $!;

  while (<$in>) {

    chomp;

    if (/File/) {
      my $key = (split /:/)[1];
      push @{ $hoa{$key} }, "Filename\n";
    }

    if (/XML/ ... /File/) {
      my $xmlfile = $1;
      push @{ $hoa{$key} }, "XML file is $xmlfile\n";
    }

    if (/Important/) {
      push @{ $hoa{$key} }, "Severity is $_\n";
    }

    if (/^\D/) {
      next if /Important/;
      push @{ $hoa{$key} }, "Given comment is $_\n";
    }

    push @{ $hoa{$key} }, "this string\n";
  }

  close $in;
}

open my $out, '>', $outfile or die $!;

foreach my $k (keys %hoa) {
  foreach my $l (@{ $hoa{$k} }) {
    print $out $l, "\n";
  }
}

close $out;
于 2012-07-20T14:47:20.227 回答
1

我怀疑根据您的代码,每次循环都不会调用设置 $key 的行,并且您不会触发任何其他 if 语句。

这会将“这个字符串”附加到数组的末尾。基于您在数组末尾获得 3 个“此字符串”,我怀疑两行没有通过 if (/FILE/) 或任何其他 if 语句。这将使 $key 值保持不变,最后,您将使用 $key 设置时的最后一个值将“此字符串”附加到数组中。

于 2012-07-20T13:47:26.037 回答
1

这会将字符串附加"this string"到 hash 的每个元素%hoa,这些元素是数组引用:

for (values(%hoa)) { push @{$_}, "this string"; }

把它放在你的while循环之外,你会在每个元素的末尾打印“这个字符串” %hoa

它将在找到undefined 元素的地方自动激活数组引用。如果它不能将一个元素作为数组解引用,它也会阻塞,如果它找到一个简单的标量并且没有在严格的条件下运行,它将通过符号引用来操作数组:

my %autoviv = ( a => ['foo'], b => undef );
push @$_, "PUSH" for values %autoviv;        # ( a => ['foo', 'PUSH'], b => ['PUSH'] )

my %fatal = ( a => {} );
push @$_, "PUSH" for values %fatal;          # FATAL:  "Not an ARRAY reference at..."

my %dangerous = (a => "foo");
push @$_, "PUSH" for values %dangerous;      # Yikes!  @foo is now ("PUSH")

use strict;
my %kablam = (a => "foo");
push @$_, "PUSH" for values %kablam;         # "Can't use string ("foo") as an ARRAY ref ..."
于 2012-07-20T14:20:07.777 回答
0

据我了解,使用命令遍历哈希map以修改其键。一个例子:

编辑:我进行了编辑,因为我意识到该map命令可以分配给相同的哈希。无需创建一个新的。

#!/usr/bin/perl

use warnings;
use strict;
use Data::Dumper;

my %hash = qw|
    key1    value1
    key2    value2
    key3    value3
|;

my %hash = map { $_ . "this string" => $hash{ $_ } } keys %hash;

print Dump \%hash;

像这样运行它:

perl script.pl

具有以下输出:

$VAR1 = {
          'key3this string' => 'value3',
          'key2this string' => 'value2',
          'key1this string' => 'value1'
        };
于 2012-07-20T13:41:52.433 回答