You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Perl中实现哈希元素的同行对齐打印?

Perl哈希数组输出列错位问题修复

问题描述

编写Perl脚本读取多个CSV文件并将数据存入哈希数组(HoA),但输出时各列元素错位分行,无法实现对应列元素在同一行对齐展示。

原代码

#!/usr/bin/perl
#use Data::Dumper;
my $file3 = 'file1.csv';
my $file2 = 'file2.csv';
my $file1 = 'file3.csv';

open (my $fh_dest, ">", "outputfile.csv") or die "Can't open > outputfile.csv: $!";

my %HoA1;
my %HoA2;
my %HoA3;
open (MODIFIED_FILE2, $file1) or  die ("Could not open $file1!");
while(<MODIFIED_FILE2>){ 
   chomp;
   my ($k, $v1,$v2,$v3,$v4) = split /,/,$_,5;
   push @{$HoA1{'MODIFIED_FILE2'}{$k}},$v1,$v2,$v3,$v4;
}
close(MODIFIED_FILE2);

open (MODIFIED_FILE1, $file2) or  die ("Could not open $file2!");
while(<MODIFIED_FILE1>){ 
   chomp;
   my ($k, $v1,$v2,$v3) = split /,/,$_,4;
   push @{$HoA2{'MODIFIED_FILE1'}{$k}},$v1,$v2,$v3;
}
close(MODIFIED_FILE1);

open (BASE_FILE, $file3) or die ("Could not open $file3!");
while(<BASE_FILE>){ 
   chomp;
   my ($k, $v1,$v2,$v3) = split /,/,$_,4;
   push @{$HoA3{'BASE_FILE'}{$k}},$v1,$v2,$v3;
}
close(BASE_FILE);

#print $fh_dest Dumper \%HoA;
foreach my $MODIFIED_FILE2 (keys %{ $HoA1{'MODIFIED_FILE2'} }) {
   if (exists $HoA3{'BASE_FILE'}{$MODIFIED_FILE2}) {
    print $fh_dest "-" x 60, "\n";
    print $fh_dest "$MODIFIED_FILE2\nMODIFIED_FILE2   MODIFIED_FILE1     BASE_FILE\n";
        print $fh_dest "-" x 60, "\n";

        foreach my $class_BASE_FILE ( @{$HoA3{'BASE_FILE'}{$MODIFIED_FILE2}} ) { 
    printf $fh_dest "%-20s%-20s%s\n",$class_MODIFIED_FILE2,$class_MODIFIED_FILE1,$class_BASE_FILE;
    }
    foreach my $class_MODIFIED_FILE1 ( @{$HoA2{'MODIFIED_FILE1'}{$MODIFIED_FILE2}} ) {
    printf $fh_dest "%-20s%s\n",$class_MODIFIED_FILE2,$class_MODIFIED_FILE1;
    }
    foreach my $class_MODIFIED_FILE2 ( @{$HoA1{'MODIFIED_FILE2'}{$MODIFIED_FILE2}} ) {
    printf $fh_dest "%s\n",$class_MODIFIED_FILE2;
    }
      print $fh_dest "\n";
}
 

   elsif (exists $HoA2{'MODIFIED_FILE1'}{$MODIFIED_FILE2}) {
    print $fh_dest "-" x 60, "\n";
    
    print $fh_dest "$MODIFIED_FILE2\nMODIFIED_FILE2   MODIFIED_FILE1     BASE_FILE\n";
    print $fh_dest "-" x 60, "\n";
    
    foreach my $class_MODIFIED_FILE1 ( @{$HoA2{'MODIFIED_FILE1'}{$MODIFIED_FILE2}} ) {
    printf $fh_dest "%-20s%s\n",$class_MODIFIED_FILE2,$class_MODIFIED_FILE1;
    }  
    foreach my $class_MODIFIED_FILE2 ( @{$HoA1{'MODIFIED_FILE2'}{$MODIFIED_FILE2}} ) {
    printf $fh_dest "%s\n",$class_MODIFIED_FILE2;
    }
      print $fh_dest "\n";
  }


   else {
    print $fh_dest "-" x 60, "\n"; 
    print $fh_dest "$MODIFIED_FILE2\nMODIFIED_FILE2   MODIFIED_FILE1     BASE_FILE\n";
    print $fh_dest "-" x 60, "\n";

    foreach my $class_MODIFIED_FILE2 ( @{$HoA1{'MODIFIED_FILE2'}{$MODIFIED_FILE2}} ) {
    printf $fh_dest "%s\n",$class_MODIFIED_FILE2;
    }  
      print $fh_dest "\n";
  }
}

close ($fh_dest);

当前输出

------------------------------------------------------------
Dora
MODIFIED_FILE2    MODIFIED_FILE1     BASE_FILE
------------------------------------------------------------
                    34
                    Malaysian
                    Malay 
34
Malaysian
Arab
B- 

------------------------------------------------------------
Boszor
MODIFIED_FILE2    MODIFIED_FILE1     BASE_FILE
------------------------------------------------------------
                                        91
                                        Mexico
                                        Chinese
                    91
                    Mexico
                    Chinese
91
Mexico
Chinese
AB+

------------------------------------------------------------
Szundi
MODIFIED_FILE2    MODIFIED_FILE1     BASE_FILE
------------------------------------------------------------
                                        23
                                        German
                                        Indian
                    23
                    German
                    Indian
23
German
Indian
AB-

期望输出

-----------------------------------------------------------
Dora
MODIFIED_FILE2    MODIFIED_FILE1     BASE_FILE
------------------------------------------------------------
34                        34
Malaysian               Malaysian
Malay                    Arab
B- 

------------------------------------------------------------
Boszor
MODIFIED_FILE2    MODIFIED_FILE1     BASE_FILE
------------------------------------------------------------
91                         91                   91
Mexico                    Mexico              Mexico
Chinese                   Chinese             Chinese
AB+
 
------------------------------------------------------------
Szundi
MODIFIED_FILE2    MODIFIED_FILE1     BASE_FILE
------------------------------------------------------------
23                         23                   23
German                    German              German
Indian                    Indian              Indian
AB-

问题原因及修复方案

问题根源

原代码用三个独立的foreach循环分别打印三列数据,导致每列的行依次输出,无法对齐;同时存在未定义变量直接使用的错误。

修复后的代码

#!/usr/bin/perl
#use Data::Dumper;
my $file3 = 'file1.csv';
my $file2 = 'file2.csv';
my $file1 = 'file3.csv';

open (my $fh_dest, ">", "outputfile.csv") or die "Can't open > outputfile.csv: $!";

my %HoA1;
my %HoA2;
my %HoA3;
open (MODIFIED_FILE2, $file1) or  die ("Could not open $file1!");
while(<MODIFIED_FILE2>){ 
   chomp;
   my ($k, $v1,$v2,$v3,$v4) = split /,/,$_,5;
   push @{$HoA1{'MODIFIED_FILE2'}{$k}},$v1,$v2,$v3,$v4;
}
close(MODIFIED_FILE2);

open (MODIFIED_FILE1, $file2) or  die ("Could not open $file2!");
while(<MODIFIED_FILE1>){ 
   chomp;
   my ($k, $v1,$v2,$v3) = split /,/,$_,4;
   push @{$HoA2{'MODIFIED_FILE1'}{$k}},$v1,$v2,$v3;
}
close(MODIFIED_FILE1);

open (BASE_FILE, $file3) or die ("Could not open $file3!");
while(<BASE_FILE>){ 
   chomp;
   my ($k, $v1,$v2,$v3) = split /,/,$_,4;
   push @{$HoA3{'BASE_FILE'}{$k}},$v1,$v2,$v3;
}
close(BASE_FILE);

foreach my $key (keys %{ $HoA1{'MODIFIED_FILE2'} }) {
    print $fh_dest "-" x 60, "\n";
    print $fh_dest "$key\nMODIFIED_FILE2   MODIFIED_FILE1     BASE_FILE\n";
    print $fh_dest "-" x 60, "\n";

    # 获取三个数组的引用,不存在则设为空数组
    my $arr1 = $HoA1{'MODIFIED_FILE2'}{$key} // [];
    my $arr2 = $HoA2{'MODIFIED_FILE1'}{$key} // [];
    my $arr3 = $HoA3{'BASE_FILE'}{$key} // [];

    # 取最大数组长度,确保所有行都被处理
    my $max_len = scalar @$arr1;
    $max_len = scalar @$arr2 if scalar @$arr2 > $max_len;
    $max_len = scalar @$arr3 if scalar @$arr3 > $max_len;

    # 按索引遍历,同一行打印三列对应元素
    for my $i (0..$max_len-1) {
        my $val1 = $arr1->[$i] // '';
        my $val2 = $arr2->[$i] // '';
        my $val3 = $arr3->[$i] // '';
        printf $fh_dest "%-20s%-20s%s\n", $val1, $val2, $val3;
    }

    print $fh_dest "\n";
}

close ($fh_dest);

修复说明

  1. 按索引同步遍历:不再单独循环每个数组,而是根据索引同时获取三个数组的对应元素,确保同一行输出对应列内容。
  2. 处理数组长度差异:取三个数组中最长的长度作为循环次数,不存在的元素用空字符串填充,避免遗漏数据。
  3. 优化变量命名:将混淆的键名变量改为$key,避免歧义;直接从数组取元素,解决未定义变量的问题。

内容的提问来源于stack exchange,提问作者suba suba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 03:32:12