расположить значение в столбцах согласно значению в 1-м столбце - PullRequest
0 голосов
/ 11 января 2019

У меня есть файл со следующими данными

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

Значения в первом столбце в некоторых местах повторяются я хочу о / п, как указано ниже

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

Он должен печатать уникальные значения столбца 1, а затем пробел, а затем печатать соответствующие значения другого столбца в одной строке, расположенной в порядке возрастания.

Я попробовал ниже:

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

здесь я не могу напечатать все значения перед значением в 1-м столбце

для 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

здесь я не могу напечатать все значения перед значением в 1-м столбце

Ответы [ 4 ]

0 голосов
/ 13 января 2019

Чтобы исправить свой 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

$
0 голосов
/ 11 января 2019

С GNU awk для истинных многомерных массивов и sorted_in:

$ cat tst.awk
BEGIN { FS="," }
{
    for (i=2; i<=NF; i++) {
        keyVals[$1][$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

Вышеописанное будет работать независимо от того, сколько полей у вас в каждой строке, и удалит дубликаты значений, когда они встречаются в нескольких строках для одного и того же значения ключа.

0 голосов
/ 12 января 2019

Это может сработать для вас (GNU sed):

sed -r 'H;x;s/((\n[^\n,]*),[^\n]*)(.*)\2([^\n]*)\n?/\1\4\3/;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]*/\2 \1/;P;:c;tc;s/[^\n]*\n//;tb;d' file

Скрипт работает в двух частях. В первой части обработки строки файла хранятся в памяти и уменьшаются в размере путем добавления значений одного и того же ключа к одному ключу. В конце файла начинается вторая часть обработки. Каждая строка разбита на две части, добавленные значения сортируются и снова добавляются к ключу, печатаются и удаляются до тех пор, пока все строки не будут обработаны.

0 голосов
/ 11 января 2019

многоступенчатый

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

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