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

如何用Perl/Awk合并同文件匹配列并保留所有行?

搞定Perl脚本丢空行的问题,实现按第5列合并第6列值

嘿,我来帮你解决这个脚本的问题!首先咱们先理清楚你的需求和现有脚本的问题:

你的需求和输入输出

你有个file1.txt文件,内容是:

1 101 111 BCX A@WWW 123
1 298 306 CCC A@QQQ 234
1 299 308 CCD A@QQQ 
1 299 309 DDD A@ZZZ 345
1 299 309 DDD A@ZZZ 678

想要实现的是:只要第5列内容相同,所有对应行的第6列都要统一成合并后的值(比如A@QQQ对应的行,哪怕原来第6列是空的,也要改成234;A@ZZZ的行都改成345,678),同时要保留所有行,不能丢任何一行。但你现在用的脚本会把第6列为空的行弄丢,得改改。

原脚本为啥会丢行?

原脚本的逻辑是逐行对比当前行和上一行的第5列,只有遇到不同的才输出上一行的内容,而且没有提前记录每个第5列对应的完整合并值,碰到空第6列的行时,没办法正确匹配到对应的合并值,自然就丢了这些行。另外原脚本用制表符输出,和你要的空格分隔格式也不符。

修改后的解决方案

咱们换个思路,先把所有行的信息收集全,再统一处理输出,这样就不会丢任何行啦。下面是修改后的Perl命令:

perl -lane '
    BEGIN { %col5_map = () }
    # 第一步:先收集每个第5列对应的所有非空第6列值
    $col5_map{$F[4]} //= [];
    push @{$col5_map{$F[4]}}, $F[5] if defined $F[5] && $F[5] ne "";
    # 把每一行的内容存起来,后面输出用
    push @lines, [@F];
    # 所有行读完后,处理合并值并输出
    END {
        # 对每个第5列的去重并拼接成目标格式
        foreach my $key (keys %col5_map) {
            my %unique_vals = map { $_ => 1 } @{$col5_map{$key}};
            $col5_map{$key} = join(",", sort keys %unique_vals);
        }
        # 遍历所有存储的行,替换第6列后输出
        foreach my $line (@lines) {
            my @fields = @$line;
            # 替换第6列:如果有对应合并值就用,没有就留空
            $fields[5] = $col5_map{$fields[4]} // "";
            # 用空格分隔输出,和输入格式一致
            print join(" ", @fields);
        }
    }
' file1.txt

运行后的输出

执行这个命令后,就能得到你想要的结果:

1 101 111 BCX A@WWW 123
1 298 306 CCC A@QQQ 234
1 299 308 CCD A@QQQ 234
1 299 309 DDD A@ZZZ 345,678
1 299 309 DDD A@ZZZ 345,678

关键改动说明

  • 用%col5_map哈希表提前把每个第5列对应的所有有效第6列值收集起来,确保不会漏掉任何组的有效值;
  • 用@lines数组把所有行的内容都存下来,保证输出时能保留原始的行顺序和所有行;
  • 在END块里对每个第5列的数值去重排序,然后统一替换每行的第6列,确保相同第5列的行第6列完全一致;
  • 用join(" ", @fields)保持和输入一致的空格分隔格式,避免原脚本的制表符问题;
  • 用// ""处理极端情况,如果某个第5列没有任何有效第6列值,就留空,不会出现乱码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:34:13