Perl解析无唯一列的三列文本文件,求替代哈希的实现方法
解决方法
因为所有字段都没有唯一性,直接用普通哈希会导致重复键覆盖旧数据,这里给你两种实用的实现方式:
方式一:返回所有条目组成的数组
这种方式会完整保留文件里的每一行数据,适合需要遍历所有记录的场景。修改你的代码如下:
#!/usr/bin/perl use strict; use warnings; my $file = "/path/to/text.txt"; # 接收数组引用并转为数组 my @info = @{parseCfg($file)}; # 遍历所有记录 foreach my $record (@info) { print "姓名: $record->{name}, 宠物: $record->{pet}, 地址: $record->{address}\n"; } sub parseCfg { my $file = shift; # 用数组存储所有记录 my @data; return \@data if !(-e $file); open(my $fh, "<", $file) or die "Can't open < $file: $!"; print "-I-: Reading from config file: $file\n"; while (<$fh>) { # 跳过注释和空行 next if /^#/ || /^\s+$/; # 去除行尾换行符 chomp; my @fields = split(" ", $_); # 修正变量名:$son改为$pet my ($name, $pet, $address) = @fields; # 将当前记录存为哈希,推入数组 push @data, { name => $name, pet => $pet, address => $address }; } close $fh; # 返回数组引用 return \@data; }
方式二:按姓名分组存储(哈希+数组)
如果需要按姓名批量查看对应的宠物和地址,可以用哈希的键作为姓名,值是对应记录的数组,相同姓名的条目会被归在一起:
#!/usr/bin/perl use strict; use warnings; my $file = "/path/to/text.txt"; my %info = %{parseCfg($file)}; # 遍历每个姓名对应的记录 foreach my $name (keys %info) { print "=== 姓名: $name ===\n"; foreach my $record (@{$info{$name}}) { print "宠物: $record->{pet}, 地址: $record->{address}\n"; } } sub parseCfg { my $file = shift; # 哈希的键是姓名,值是记录数组的引用 my %data; return \%data if !(-e $file); open(my $fh, "<", $file) or die "Can't open < $file: $!"; print "-I-: Reading from config file: $file\n"; while (<$fh>) { next if /^#/ || /^\s+$/; chomp; my @fields = split(" ", $_); my ($name, $pet, $address) = @fields; # 将当前记录推入对应姓名的数组 push @{$data{$name}}, { pet => $pet, address => $address }; } close $fh; return \%data; }
代码说明
- 两种方式都修正了原代码里的变量名错误(
$son改为$pet),并添加chomp去除行尾换行符。 - 方式一适合需要完整保留所有行顺序的场景,主程序可直接遍历数组获取每一条数据。
- 方式二适合需要按姓名分组查询的场景,能快速找到同一姓名对应的所有宠物和地址信息。
内容的提问来源于stack exchange,提问作者Blurman
相关产品推荐
相关产品推荐

