AWK Объединить строки с одинаковым первым столбцом в определенный формат - PullRequest
1 голос
/ 07 ноября 2019

Я хотел бы объединить строки файла с разделителями табуляции (по 9 столбцов) с одинаковыми $ 1 в конкретный формат.

ВХОД:

DIA   55tyr  10 HOM   1 olig_al  ....
ALOP  66tel  11 HET   3 alin_et  .... 
ALOP  128ryp 11 HET   3 ivi_es   ....
ALOP  131dat 11 HET   3 osi_et   ....
ANDY  12dou  13 WILD  4 sas_rar  ....
KOLIK 16dev  14 HET   6 levi_lol ... 

ВЫХОД:

DIA   55tyr  10 HOM   1 olig_al  ....
ALOP  66tel_128ryp_131dat 11 HET_HET_HET 3 alin_et_ivi_es_osi_et ....
ANDY  12dou  13 WILD  4 sas_rar  ....
KOLIK 16dev  14 HET   6 levi_lol ...

A может объединить его и написать строки одну за другой в одной строке с этим:

awk -F'\t' -v OFS='\t' '{x=$1;$1="";a[x]=a[x]$0}END{for(x in a)print x,a[x]}'

и после этого использовать некоторые условия. Можно ли написать код awk, чтобы объединить строки с одинаковыми $ 1 и соединить $ 2, $ 4, $ 6, $ 7, $ 8, $ 9 с разделителем «_», а строки $ 3 и $ 5 будут уникальными, как в выводе? Спасибо за помощь.

Ответы [ 2 ]

1 голос
/ 07 ноября 2019

1-е решение (объединить все поля с одним и тем же первым полем): Не могли бы вы попробовать следующее. Это позаботится о последовательности $ 1, в которой это происходит, и будет отображать вывод таким же образом. Также это будет выполняться до максимального количества полей (во всем Input_file).

awk '
!a[$1]++{
  b[++count]=$1
}
{
  val=val>NF?val:NF
  for(i=2;i<=NF;i++){
    c[$1,i]=(c[$1,i]?c[$1,i] "_":"")$i
  }
}
END{
  for(i=1;i<=count;i++){
    printf("%s ",b[i])
    for(j=2;j<=val;j++){
      printf("%s %s",c[b[i],j]?c[b[i],j]:0,j==val?ORS:OFS)
    }
  }
}'  Input_file

Вывод будет следующим:

DIA 55tyr  10  HOM  1  olig_al 
ALOP 66tel_128ryp_131dat  11_11_11  HET_HET_HET  3_3_3  alin_et_ivi_es_osi_et 
ANDY 12dou  13  WILD  4  sas_rar 
KOLIK 16dev  14  HET  6  levi_lol 


2-е решение (объединить только четные поля):

awk '
!a[$1]++{
  b[++count]=$1
}
{
  val=val>NF?val:NF
  for(i=2;i<=NF;i++){
    if(i%2==0){
    c[$1,i]=(c[$1,i]?c[$1,i] "_":"")$i
    }
    else{
        c[$1,i]=$i
    }
  }
}
END{
  for(i=1;i<=count;i++){
    printf("%s ",b[i])
    for(j=2;j<=val;j++){
      printf("%s %s",c[b[i],j]?c[b[i],j]:0,j==val?ORS:OFS)
    }
  }
}' Input_file

Вывод будет следующим:

DIA 55tyr  10  HOM  1  olig_al 
ALOP 66tel_128ryp_131dat  11  HET_HET_HET  3  alin_et_ivi_es_osi_et 
ANDY 12dou  13  WILD  4  sas_rar 
KOLIK 16dev  14  HET  6  levi_lol 
1 голос
/ 07 ноября 2019

Вот один из них.

b[] - это массив, в котором хранятся номера полей, которые необходимо добавить вместе с _ с, a[$1] содержит запись данных для идентичных $1 с и перестраивается каждый раз $1 встречается снова.

Относительно $ 3 и $ 5 строка будет уникальной программа предполагает, что они остаются постоянными (как в примере) и взяты из последнего увиденного экземпляра $1.

$ awk '
BEGIN {
    b[2];b[4];b[6];b[7];b[8];b[9]                   # these fields are appended
}
{
    if($1 in a) {                                   # search if in a already
        n=split(a[$1],tmp,"\t")                     # split on a tab from a
        for(i=1;i<=n;i++) {                         # iterate all elements
            if(i in b)                              # if appending needed
                $i=tmp[i] "_" $i                    # append
            a[$1]=(i==1?"":a[$1]) $i (i==n?"":"\t") # and rebuild a entry
        }
    } else                                          # if not in a
        a[$1]=$0                                    # well put it in
}
END {                                               # in the END
    for(i in a)                                     # iterate 
        print a[i]                                  # and output
}' file

Вывод:

ANDY    12dou   13      WILD    4       sas_rar ....
DIA     55tyr   10      HOM     1       olig_al ....
KOLIK   16dev   14      HET     6       levi_lol        ...
ALOP    66tel_128ryp_131dat     11      HET_HET_HET     3   alin_et_ivi_es_osi_et   ...._...._....

Обновление: Добавление однострочной версии (на всякий случай:)

$ awk 'BEGIN {b[2];b[4];b[6];b[7];b[8];b[9]}{if($1 in a) {n=split(a[$1],tmp,"\t");for(i=1;i<=n;i++){if(i in b)$i=tmp[i] "_" $i;a[$1]=(i==1?"":a[$1]) $i (i==n?"":"\t")}} else a[$1]=$0}END {for(i in a)print a[i]}' file
...