我有一个如下输入文件:
start
f1="apple"
f2="banana"
f3="berry"
end
start
f1="guava"
f2="banana"
f3="berry"
end
start
f1="apple"
f2="cucumber"
f3="orance"
end
我打算创建一个值为数组的哈希。
所有标签都在一个临时数组中,并且在标签之间有一个字段f1
,其值将是散列的关键字。
从开始到结束它将存储在临时数组中,一旦到达结束,数组将被推送为hash的值,其中key为最新字符串f1=
后面的值
我编写了以下代码,但它不起作用。
有人可以在此建议任何更正吗?
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
open( FILE, "<", "temp2" );
my %FILEDATA;
my @tmp = ();
my $fruit = "";
while ( <FILE> ) {
chomp( $_ );
push @tmp, $_;
my @linefields = split( '=', $_ );
if ( $linefields[0] =~ /f1/ ) {
$fruit = $linefields[1];
}
if ( $_ =~ /end/ ) {
if ( $fruit eq "apple" ) {
if ( exists $FILEDATA{"apple"} ) {
push( @{ $FILEDATA{"apple"} }, @tmp );
}
else {
$FILEDATA{"apple"} = @tmp;
}
}
elsif ( $fruit eq "guava" ) {
if ( exists $FILEDATA{"guava"} ) {
push( @{ $FILEDATA{"guava"} }, @tmp );
}
else {
$FILEDATA{"guava"} = @tmp;
}
}
undef @tmp;
}
}
print Dumper( \%FILEDATA );
答案 0 :(得分:1)
我假设这是家庭作业
以下是一些指南
$_
是许多Perl运算符的默认参数。特别是,chomp( $_ )
可以写为chomp
,split( '=', $_ )
应为split /=/
,if ( $_ =~ /end/ ) { ... }
可以为if ( /end/ )
无需测试$fruit
的值。如果它的值是您想要的密钥,那么您应该使用$FILEDATA{$fruit}
$FILEDATA{"apple"} = @tmp
将$FILEDATA{"apple"}
设置为@tmp
中元素的数量。您需要使用$FILEDATA{"apple"} = \@tmp
在使用push
之前,无需检查哈希值或数组元素是否存在。如果您只是push @{ $FILEDATA{apple} }, 'ff'
,那么将创建数组
if ( $linefields[0] =~ /f1/ )
测试$linefields[0]
是否包含字符串f1
。要测试您想要的平等if ( $linefields[0] eq 'f1' )
您不应使用undef @data
或@data = undef
清空数组或哈希值。正确的方法是@data = ()
。要清空标量,请使用$val = undef
以下是代码的外观
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
open FILE, "<", "fruit.txt";
my %data;
my @tmp;
my $fruit;
while ( <FILE> ) {
chomp;
push @tmp, $_;
my @fields = split /=/;
if ( $fields[0] eq 'f1' ) {
$fruit = $fields[1];
}
if ( /end/ ) {
push @{ $data{$fruit} }, [ @tmp ];
@tmp = ();
}
}
print Dumper( \%data );
$VAR1 = {
'"guava"' => [
[
'start',
'f1="guava"',
'f2="banana"',
'f3="berry"',
'end'
]
],
'"apple"' => [
[
'start',
'f1="apple"',
'f2="banana"',
'f3="berry"',
'end'
],
[
'start',
'f1="apple"',
'f2="cucumber"',
'f3="orance"',
'end'
]
]
};
这就是我写它的方式
#!/usr/bin/perl
use strict;
use warnings;
use autodie;
use Data::Dumper;
my $file = 'fruit.txt';
open my $fh, '<', $file
or die qq{Unable to open "$file": $!};
my ( %data, @block, $fruit );
while ( my $line = <$fh> ) {
chomp $line;
push @block, $line if @block or $line eq 'start';
$fruit = $1 if $line =~ /^f1="(\w+)"/;
if ( $line eq 'end' ) {
push @{ $data{$fruit} }, [ @block ];
@block = ();
$fruit = undef;
}
}
print Dumper \%data;
请注意,您不应使用undef @data
或@data = undef
清空数组或哈希值。正确的方法是@data = ()
答案 1 :(得分:-1)
试试此代码
my $file = 'fruits.txt';
my %hash;
open (my $fh, '<', $file) or die "Could not open $!";
while(my $line = <$fh>) {
next if $line =~ /start/;
next if $line =~ /end/;
if ($line =~ /f1/) {
my ($key, $val) = split /=/, $line;
push @{$hash{$key}}, $val;
}
if ($line =~ /f2/) {
my ($key, $val) = split /=/, $line;
push @{$hash{$key}}, $val;
}
if ($line =~ /f3/) {
my ($key, $val) = split /=/, $line;
push @{$hash{$key}}, $val;
}
}
print Dumper(\%hash);