我有以下哈希散列:
my %MacroA = ('Category' => {}, 'Item' => {}, 'Description' => {}, 'Score' => {});
我想要的是遍历文件,然后将新元素添加到不同的哈希值。让我们说该行包含“布局”我想在每次看到它时将其存储在“类别”中
我所做的是:
while (my $line = <$file>) {
if ($line =~ /\b(layout)\b,/) {
foreach my $categories (keys $MacroA{'Category'}) {
$MacroA{Category} = $1;
}
}
答案 0 :(得分:3)
您的问题非常容易引起混淆,但您的问题似乎是因为您在引用而不是哈希上执行keys
。较新的perls确实支持这一点,但你可能使用旧版本。
在您的示例中$MacroA{'Category'}
返回哈希引用,而不是哈希。您使用'Category' => {}
初始化哈希,{}
是对空匿名哈希的引用。
要将哈希引用转换为哈希,请使用%{ ... }
表示法;在这种情况下,你要写keys %{ $MacroA{'Category'} }
。是的,这很难看,这就是为什么Perl被改为支持引用的keys
。
但请注意,您的下一行是$MacroA{Category} = $1;
,它将使用$1
中的任何内容替换引用,可能是字符串"layout"
。这不是一个引用,所以下一次while循环时,你的脚本将会完成。你可能想要做一个多级哈希,比如$MacroA{Category}{$1} = $file
或类似的东西,这取决于你想要在哈希中建立什么数据,但是你真正想要实现的是什么。另一个建议阵列散列的答案可能就是你想要的。在这种情况下,如果使用较旧的perl,则表示法@{ ... }
会将数组引用转换为可与push
一起使用的数组。
答案 1 :(得分:2)
看起来你正试图在这里做一些命名列的事情。这是 非常直接,如果你知道怎么做。
从你的评论到彼得(“[我]想要存储”布局“各自 行至'描述'“)这是该代码允许您执行的操作:存储它。
因为我看到哈希的主要情况是记录本身,这是唯一的哈希
这个演示使用。它将它们存储在一个数组中。我真的不明白你的意思
想从你的例子中索引它们。你似乎对你有点困惑
想要处理它们。当然,处理每一行都没有用
其中包含'layout'
,然后将其存储为“类别”字段。
use strict;
use warnings;
my @columns = qw<field1 field2 field3 field4>;
my @list;
my $fh = \*::DATA;
my $header = <$fh>;
if ( substr( $header, 0, 1 ) eq '#' ) {
( $header ) = $header =~ m/#(.*)/;
$header =~ s/\s+$//;
@columns = split /,\s*/, $header;
}
else {
seek( $fh, 0, 0 ); # go back
}
# optional statement to capitalize field names
@columns = map { ucfirst } @columns;
while ( my $line = <$fh> ) {
next unless $line =~ m/^\s*layout\b/;
$line =~ s/\s*$//;
# store fields by hash slice in the tip of the array
@{ $list[@list] }{ @columns } = split /,\s*/, $line;
}
__DATA__
#category, item, description, score
layout,f.4,Macro placement clearance,pass
layout,f.14,No area congestion,pass
layout,f.17,placement collar diode,fail
layout,f.18,placement collar buffer,pass
layout,f.26,tie connection,fail
layout,f.28,CTS allowed cell,fail
layout,f.29,CTS allowed layed,pass
layout,f.31,Clock De-cap cell,fail
layout,f.33,Clock non default rule,fail
虽然这不是你想要的一切,但是将记录复制到 一个数组是简单“处理它”的模型,我们可以做这样的事情 相反:
my %by_item;
while ( my $line = <$fh> ) {
next unless $line =~ m/^\s*layout\b/;
$line =~ s/\s*$//;
my %h;
@h{ @columns } = split /,\s*/, $line;
$by_item{ $h{Item} } = \%h;
### OR
# push @{ $by_item{ $h{Item} } }, %h;
}
你也可以这样做:
my %by_field;
...
$by_field{Item}{ $h{Item} }
= $by_field{Description}{ $h{Description} }
= \%h
;
答案 2 :(得分:1)
我认为你需要一个数组哈希:
my %MacroA = ('Category' => [], 'Item' => [], 'Description' => [], 'Score' => []);
while (my $line = <$file>) {
if ($line =~ /\b(layout)\b,/) {
foreach my $categories (keys $MacroA{'Category'}) {
push $MacroA{Category}, $1;
}
}
答案 3 :(得分:1)
你的问题令人困惑。只需在“类别”键中添加“布局”很简单,不涉及循环:
while (my $line = <$file>) {
if ($line =~ /\blayout\b,/) {
$MacroA{Category} = 'layout';
}
}
答案 4 :(得分:1)
下面是一个完整的程序,分为不同的块。要运行它,请将答案复制并粘贴到名为populate
的文件中,但要删除评论部分,例如此段落。
几乎所有的Perl程序(特别是在你还是初学者的时候)都应该以
开头#! /usr/bin/env perl
use strict;
use warnings;
第一行告诉系统如何执行程序。启用strict
和warnings
pragmata将帮助您避免常见错误,并帮助您解释在您看到令人惊讶的行为时您的计划正在执行的操作。
根据您的问题,您需要的数据结构是一个哈希数组。数组的每个“行”或元素将对应于输入文件中的一行,其格式为
# { Category => '...', Item => '...', Description => '...', Score => '...' }
程序还将从输入中读取列名。
代码使用Perl的“菱形运算符”来读取每行输入。如果存在,chomp
会删除尾随换行符。
如果该行告诉我们标题名称(即。,它以#
开头),我们将每个字段存储在@columns
中。 ucfirst
位可能不熟悉:你 pper c 评论字符串的第一个字符。由于有多个列名称,我们使用map
将ucfirst
应用于每个。
否则,该行代表数据行。我们将split
行划分为以逗号分隔的字段,并将它们加载到新的哈希中。 push
行将引用(使用散列前的反斜杠创建)添加到@MacroA
的末尾。
my @MacroA;
my @columns;
while (<>) {
chomp;
if (s/^#//) { # / fix Stack Overflow coloring
@columns = map ucfirst, split /\s*,\s*/; # / ditto
}
else {
my %row;
@row{@columns} = split /,/;
push @MacroA, \%row;
}
}
请注意,上面的拆分是naïaut; ve。要处理常规CSV输入,请使用CSV modules on CPAN之一。
Data::Dumper模块对于快速打印复杂数据结构的内容非常有用。将其粘贴在调试工具包中。
use Data::Dumper;
$Data::Dumper::Indent = $Data::Dumper::Terse = 1;
print Dumper \@MacroA;
__END__
给定文件input
,其内容低于
#category, item, description, score layout,f.4,Macro placement clearance,pass layout,f.14,No area congestion,pass layout,f.17,placement collar diode,fail layout,f.18,placement collar buffer,pass layout,f.26,tie connection,fail layout,f.28,CTS allowed cell,fail layout,f.29,CTS allowed layed,pass layout,f.31,Clock De-cap cell,fail layout,f.33,Clock non default rule,fail
示例运行如下。
$ perl populate input [ { 'Score' => 'pass', 'Item' => 'f.4', 'Description' => 'Macro placement clearance', 'Category' => 'layout' }, { 'Score' => 'pass', 'Item' => 'f.14', 'Description' => 'No area congestion', 'Category' => 'layout' }, { 'Score' => 'fail', 'Item' => 'f.17', 'Description' => 'placement collar diode', 'Category' => 'layout' }, { 'Score' => 'pass', 'Item' => 'f.18', 'Description' => 'placement collar buffer', 'Category' => 'layout' }, { 'Score' => 'fail', 'Item' => 'f.26', 'Description' => 'tie connection', 'Category' => 'layout' }, { 'Score' => 'fail', 'Item' => 'f.28', 'Description' => 'CTS allowed cell', 'Category' => 'layout' }, { 'Score' => 'pass', 'Item' => 'f.29', 'Description' => 'CTS allowed layed', 'Category' => 'layout' }, { 'Score' => 'fail', 'Item' => 'f.31', 'Description' => 'Clock De-cap cell', 'Category' => 'layout' }, { 'Score' => 'fail', 'Item' => 'f.33', 'Description' => 'Clock non default rule', 'Category' => 'layout' } ]