根据第一列中的值排列列中的值

to arrange the value in columns as per value in 1st column

我有一个包含以下数据的文件

cat text.txt
281475473926267,46,47
281474985385546,310,311
281474984889537,248,249
281475473926267,16,17
281474985385546,20,28
281474984889537,112,68

第一列中的值在某些地方重复 我想要 o/p 如下所示

cat output.txt
281475473926267 16,17,46,47
281474985385546 20,28,310,311
281474984889537 68,112,248,249

它应该打印第 1 列的唯一值,然后 space 然后它应该在一行中按升序打印其他列的相应值。

我在下面试过:

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

281474984889537 112,248
281474985385546 310,20
281475473926267 46,16

这里我无法打印第一列值前面的所有值

对于 281474984889537 它应该打印 68,112,248,249,但它只打印 112,248

我也不知道如何按升序排列。

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

281474984889537 112,248
281474985385546 310,20
281475473926267 46,16

这里我无法打印第一列值前面的所有值

多步骤

$ awk -F, '{print ,; print ,}' file             | 
  sort -k1n -k2n                                        | 
  awk 'p!={if(p) print p,a[p]; a[]=; p=; next} 
            {a[]=a[] "," } 
       END  {print p,a[p]}'                             | 
  sort -k2n

281475473926267 16,17,46,47
281474985385546 20,28,310,311
281474984889537 68,112,248,249

使用 GNU awk 实现真正的多维数组和 sorted_in:

$ cat tst.awk
BEGIN { FS="," }
{
    for (i=2; i<=NF; i++) {
        keyVals[][$i]
    }
}
END {
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (key in keyVals) {
        vals = ""
        for (val in keyVals[key]) {
            vals = (vals == "" ? "" : vals ",") val
        }
        print key, vals
    }
}

$ awk -f tst.awk file
281474984889537 68,112,248,249
281474985385546 20,28,310,311
281475473926267 16,17,46,47

无论每行有多少个字段,上面的方法都有效,并且当重复值出现在同一键值的多行时,它会删除重复值。

这可能对你有用 (GNU sed):

sed -r 'H;x;s/((\n[^\n,]*),[^\n]*)(.*)([^\n]*)\n?//;x;$!d;x;s/.//;:b;h;s/\n.*//;s/[^,]*,//;s/,/\n/g;s/.*/echo "&"|sort -n|paste -sd,/e;G;s/^([^\n]*)\n([^\n,]*),[^\n]*/ /;P;:c;tc;s/[^\n]*\n//;tb;d' file

该脚本分为两部分。在处理的第一部分,文件的行保存在内存中,并通过将相同键的值附加到单个键来减小大小。在文件末尾执行处理的第二部分。每行被分成两行,附加值被排序并重新附加到键,打印和删除,直到所有行都被处理。

要更正您的 Perl-oneliner,请使用它。

$ cat text.txt
281475473926267,46,47
281474985385546,310,311
281474984889537,248,249
281475473926267,16,17
281474985385546,20,28
281474984889537,112,68

$ cat text.txt | perl -F, -lanE ' @t1=@{$kv{$F[0]}}; push(@t1,@F[1..2]); $kv{$F[0]}=[@t1]; END { while(my($x,$y) = each(%kv)) { print "$x ",join(",",@{$y}) }}'
281474985385546 310,311,20,28
281475473926267 46,47,16,17
281474984889537 248,249,112,68

$

当您有更多列时,将上面的一行从 1..2 小幅更改为 1..$#F 即可。看看这个

$ cat > text2.txt
281475473926267,46,47,49
281474985385546,310,311
281474984889537,248,249,311,677,213
281475473926267,16,17
281474985385546,20,28
281474984889537,112,68,54,78,324,67


$ cat text2.txt | perl -F, -lanE ' @t1=@{$kv{$F[0]}}; push(@t1,@F[1..$#F]); $kv{$F[0]}=[@t1]; END { while(my($x,$y) = each(%kv)) { print "$x ",join(",",@{$y}) }}'
281474984889537 248,249,311,677,213,112,68,54,78,324,67
281474985385546 310,311,20,28
281475473926267 46,47,49,16,17

$