如何从列到行获取唯一值
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
注意:由于 awk
和 perl
都使用关联数组,打印的顺序可能与元素在文件中遇到的顺序不同。
我有一个输入文件:
> 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 ifmatch
找到匹配值:(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
注意:由于 awk
和 perl
都使用关联数组,打印的顺序可能与元素在文件中遇到的顺序不同。