如何从列到行获取唯一值

How to get the unique values from column to row

我有一个输入文件:

> cat test_mfd_1
16,281474976750348
17,281474976750348
16,281474976750348
17,281474976750348
16,281474976749447
17,281474976749447
16,281474976749447
17,281474976749447

我需要这样的输出:

281474976750348 16,17
281474976749447 16,17

第 2 列和第 1 列都有重复的值。但是作为 o/p 它应该在第 2 列中找到唯一值并打印所有相应的唯一值,如行中一样。

我正在使用 awk,我得到如下 o/p。

awk -F, '{a[]=;} END {for(i in a) print i" "a[i];}' test_mfd_1
281474976749447 17
281474976750348 17

我无法在第 2 列前面打印第 1 列的所有唯一值

对于 GNU awk:

awk -F, '{a[][]} END {for(i in a) {printf i; first=1; for (j in a[i])  if (first) {printf " " j; first=0;} else printf "," j; print ""} }' test_mfd_1
#=> 281474976749447 16,17
#=> 281474976750348 16,17

刚刚改进了你的尝试。
这个想法是使用二维数组和一个内部 for 循环。
printf 不会打印换行符,所以使用 print "" 最后追加一个新行。

这是另一个。它将逗号分隔的 </code> 值附加到 <code>a[] 但首先使用 match() 来检查该值是否已经存在:

$ awk -F, '{
    a[]=a[] (match(a[],"(^|,)"  "($|,)")?"":(a[]==""?"":","))
} 
END {
    for(i in a)
        print i,a[i]
} ' file
281474976749447 16,17
281474976750348 16,17

稍微解释一下:

  • a[]=a[] (... 附加到数组
  • match(a[],"(^|,)" "($|,)")?"" null if match 找到匹配值
  • :(a[]==""?"":",")) 或逗号(如果需要)和值

使用GNU Datamash:

$ datamash --sort -t, -g 2 unique 1 < file
281474976749447,16,17
281474976750348,16,17

如果你坚持space:

$ datamash --sort -t, -g 2 unique 1 < file | sed 's/,/ /'
281474976749447 16,17
281474976750348 16,17

sort 协助 awk

$ sort -t, -u -k2 -k1,1 file | 
  awk -F, '{a[]=a[] sep[] ; sep[]=FS} END{for(k in a) print k,a[k]}'

281474976749447 16,17
281474976750348 16,17

sep 用于延迟分隔符初始化以跳过第一个。

使用 Perl

$ cat jeevan.txt
16,281474976750348
17,281474976750348
16,281474976750348
17,281474976750348
16,281474976749447
17,281474976749447
16,281474976749447
17,281474976749447

$ perl -F, -lane ' $kv{$F[1]}{$F[0]}++; END { while(my($x,$y) = each(%kv)) { print "$x ",join(",",keys %$y) } }' jeevan.txt
281474976749447 16,17
281474976750348 16,17

$ perl -F, -lane ' $kv{$F[1]}{$F[0]}++; END { print "$_ ",join(",",keys %{$kv{$_}}) for(keys %kv) } ' jeevan.txt
281474976749447 16,17
281474976750348 16,17

$ perl -F, -lane ' push @{$kv{$F[1]}},$F[0]; END { for(keys %kv) { %p=map{ $_ => 1} @{$kv{$_}} ; print "$_ ",join(",", keys %p) } } ' jeevan.txt
281474976749447 17,16
281474976750348 16,17

$ perl -F, -lane ' push @{$kv{$F[1]}},$F[0]; END { for my $a (keys %kv) { @p=grep{ !$s{$a}{$_}++ } @{$kv{$a}} ; print "$a ",join(",", @p) } } ' jeevan.txt
281474976749447 16,17
281474976750348 16,17

$ perl -F, -lane ' push @{$kv{$F[1]}},$F[0]; END { for my $a (keys %kv) { print "$a ",join(",", grep{ !$s{$a}{$_}++ } @{$kv{$a}}) } } ' jeevan.txt
281474976750348 16,17
281474976749447 16,17

因为这类似于 SQL,您也可以使用 sqlite

$ cat ./sqllite_unique.sh
#!/bin/sh
sqlite3 << EOF
create table t1(a,b);
.separator ','
.import  t1
select b|| ' ' || group_concat(distinct a) from t1 group by b;
EOF

$ ./sqllite_unique.sh jeevan.txt
281474976749447 16,17
281474976750348 16,17

这是一个Perl:

$ perl -F, -lanE '$HoH{$F[1]}{$F[0]}++; 
                  END{for (keys %HoH) {
                         say "$_ ", join(", ", keys %{$HoH{$_}}); }}' file
281474976749447 16, 17
281474976750348 17, 16

这是一个 awk:

$ awk -F, '{a[][]} 
           END{ for (e in a){
                  s=""
                  for (x in a[e]) s=s?s ", " x:x
                  print e, s}}' file
281474976749447 16, 17
281474976750348 16, 17

注意:由于 awkperl 都使用关联数组,打印的顺序可能与元素在文件中遇到的顺序不同。