我有一个像这样的文件
key1 value1
key2 value2
key3 value3
等
我想通过分割空白处的每一行来创建一个哈希。我试过这样的
while (<FILE>) {
chomp;
my ($key, $val) = split / /;
$hash{$key} .= exists $hash{$key} ? ",$val" : $val;
}
这给出了输出
key1 => value1, key2
并忽略其余行。
当我检查是否逐行阅读时,它没有。
它不是逐行读取,而是while
循环只循环一次所有数据。
为什么会这样做?
答案 0 :(得分:2)
您将.= ",$val"
附加到每个哈希值,无论它是否先前存在,因为$hash{$key} .=
隐式创建元素$hash{$key}
,以便它可以接收分配。这意味着exists
将始终返回 true ,并且只会评估条件的第一个分支。对于任何数组或哈希元素都会发生这种情况
您的示例数据错误,因为它不包含等号=
,但我认为您的意思是仅在哈希值已包含数据时才将",$val"
附加到哈希值。如果没有与$key
对应的元素,则只需指定$val
喜欢这个
use strict;
use warnings;
my %hash;
while (<DATA>) {
chomp;
my ($key, $val) = split /=/;
if ( exists $hash{$key} ) {
$hash{$key} .= ",$val";
}
else {
$hash{$key} = $val;
}
}
use Data::Dump;
dd \%hash;
__DATA__
key1=value1
key2=value2
key3=value3
key1=value4
key2=value5
<强>输出强>
{ key1 => "value1,value4", key2 => "value2,value5", key3 => "value3" }
<强>更新强>
如果您确实想要在一行中执行此操作(尽管我建议您不这样做),您只需在代码中将exists
替换为defined
,给予
$hash{$key} .= defined $hash{$key} ? ",$val" : $val;
因为,尽管该元素是自动生成的,因此存在,但在收到第一个值之前它仍然没有值,所以仍然没有定义
但是请使用简单的if
语句,以便自动生命的变幻莫测,不会让那些必须维护代码的人感到复杂
<强>更新强>
这是另一种方式
$hash{$key} .= ',' if exists $hash{$key};
$hash{$key} .= $val;
这个和标准if
都正常工作,因为在评估.=
运算符之前测试了条件。仅当指定的值使用条件表达式时才首先执行.=
答案 1 :(得分:0)
这是另一种方式
for my $line(<FILE>){
my ($key, $val) = split(/ /,$line);
if ( exists $hash{$key} ) {
$hash{$key} .= "$val";
}
else {
$hash{$key} = $val;
}