根据第二列合并一列

根据第二列合并一列

我的文件看起来像这样:

pw1jc5ssyt6hx618,254343
ysezaratlycpuggl,254333
pht92h4adr3mrbz3,254343
hguvgstqxu3gowfg,254344
gqjp2rsjmk1a2v9c,254333
twdzyi2ddbnrfknd,254333
gcmj7krrx5x6nf8r,254341
tpqorqbyrg1nmm7s,254333
alnac47rt8d4ege3,254343

我想根据第二列合并此文件,并-作为分隔符,以便结果如下所示:

254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254344,hguvgstqxu3gowfg
254341,gcmj7krrx5x6nf8r

答案1

awk是你的朋友

$ cat 299360
ipw1jc5ssyt6hx618,254343
ysezaratlycpuggl,254333
pht92h4adr3mrbz3,254343
hguvgstqxu3gowfg,254344
gqjp2rsjmk1a2v9c,254333
twdzyi2ddbnrfknd,254333
gcmj7krrx5x6nf8r,254341
tpqorqbyrg1nmm7s,254333
alnac47rt8d4ege3,254343
$ awk -v FS="," '/^$/{next} # for empty line go to next record
                {if(NR==1){ # checking for first record
                f2[$2]=$1;next} # Adding $1 to array f2 at index $2
                else{
                if($2 in f2){ # Check if $2 is already an index in f2
                f2[$2]=f2[$2]"-"$1;next #appending "-$1" to current value
                }
                else{
                f2[$2]=$1;next
                }
                }}
                END{ # This line will be processed at the end
                for(i in f2){  # for all the indexes i in f2
                printf "%s,%s\n",i,f2[i] #printing in the desired format
                }
                }
                ' 299360
254341,gcmj7krrx5x6nf8r
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254344,hguvgstqxu3gowfg

解释

  1. FS=","– FS 是 awk 的内置变量,代表字段分隔符。将字段分隔符设置为,将设置,为分隔符。
  2. $1您可以通过、$2等方式访问字段。
  3. awk 脚本用单引号括起来; IE,'awk-script-goes-here'
  4. NR是 awk 内置变量,代表记录号(当前正在处理的记录号)。默认情况下,每一行都是一条记录。
  5. 我们f2[$2]=$1 正在设置一个f2以 field2(即$2)为索引的关联数组。
  6. $2 in f2检查索引是否已存在于数组中。
  7. if-elseprintf不言自明的。
  8. awk 中的块END仅在最后执行;即,在处理完所有记录之后。
  9. for(i in f2)是一个 for 循环结构,用于解析 awk 中的关联数组。这是另一种说法,for every index i in f2 do something
  10. 请注意,上面的for循环可能不会按顺序打印数组。不过,您可以使用sortbash 命令对数组进行排序。
  11. next转到下一条记录而不处理后面的命令。
  12. /pattern/awk 中的模式检查;该模式^$检查空行。

参考

如果你想成为 awk 的专家,有效的 awk 编程是必读的。

丑陋的单线

awk -v FS="," '/^$/{next}{if(NR==1){f2[$2]=$1;next}else{if($2 in f2){f2[$2]=f2[$2]"-"$1;next}else{f2[$2]=$1;next}}}END{for(i in f2){printf "%s,%s\n",i,f2[i]}}' 299360

笔记:理想情况下,在 awk 脚本中硬编码换行符不是一个好主意,就像在printf "%s,%s\n",i,f2[i].您可以将其替换为printf "%s,%s\n",i,f2[i];print以获得额外的便携性。

答案2

与GNU数据混合

datamash -t, -s -g 2 collapse 1 <data.txt | sed 's/,/-/2g'

结果:

254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254341,gcmj7krrx5x6nf8r
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254344,hguvgstqxu3gowfg

答案3

perl

#! /usr/bin/perl

use strict;
my %mergecol = ();

while(<>) {
  s/#.*//;            # strip comments
  next if (m/^\s*$/); # skip empty lines
  chomp;
  my ($val,$key) = split ',';
  push @{ $mergecol{$key} }, $val;
};

foreach my $k (keys %mergecol) { 
  printf "%s,%s\n", $k, join('-', @{ $mergecol{$k} } );
}

while循环读取输入并创建一个数组哈希 (HoA) 结构 - 一个关联数组,其中每个元素都是一个数组(也称为“列表”)。哈希的键是第二个字段,而每个列表的元素是具有相同第二个字段的行的第一个字段。

在脚本的末尾,每条记录打印一行 HoA,其中包含键名、逗号,然后用-.

运行为:

$ ./rock.pl rock.txt
254341,gcmj7krrx5x6nf8r
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254344,hguvgstqxu3gowfg
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3

或者作为“一行”缩短并嵌入到 shell 命令或脚本中:

$ perl -n -e '
    s/#.*//;
    next if (m/^\s*$/);
    chomp; ($v,$k)=split ","; push @{ $mc{$k} }, $v;
    END {
     foreach $k (keys %mc) { printf "%s,%s\n", $k, join("-",@{$mc{$k}}) }
    }' rock.txt 

或者

$ perl -e 'while(<>) {s/#.*//;next if (m/^\s*$/);chomp;($v,$k)=split ",";push @{$mc{$k}}, $v};
    foreach $k (keys %mc) {printf "%s,%s\n",$k,join("-",@{$mc{$k}})}' rock.txt

请注意,散列或关联数组是本质上是无序的,如果您想要排序输出,请通过管道输入或在上面的行上sort使用。(sort keys %f)foreach my $k

答案4

GNU 中的二维数组awk

awk -F, '{
  a[$2][$1]
  }
  END{
    for (i in a) {
      c=0; printf "%s,", i; 
        for (j in a[i]) {
          ++c; printf "%s%s", j, length(a[i]) == c? "\n": "-"
          }
     }
   }' file

相关内容