2017-10-16 4 views
2

Je suis en train de fusionner des lignes alternées en ce qui concerne chaque colonneComment fusionner des lignes alternatives à chaque colonne suivante?

entrée:

ind1 T G T 
    T T T 
ind2 G G T 
    G T T 

sortie souhaitée:

ind1 TT GT TT 
ind2 GG GT TT 

J'ai essayé ces commandes:

sed 'N;s/\n/ /' <input> output 

et

paste - - <input> output 

mais il ne fusionne que des lignes alternées mais en ajoutant la ligne entière, sans tenir compte des colonnes; par exemple:

ind1 T G T T T T 

ind2 G G T G T T 

Une idée utilisant bash ou python?

+1

Est-ce un exemple représentatif, ou simplement une illustration? En particulier, dans votre entrée actuelle, le nombre de colonnes est-il fixé? Les données sont-elles toujours la seule lettre «T» ou «G»? Le chef est-il toujours 'ind' suivi d'un nombre? Sont ces onglets ou espaces? – bishop

+0

est un exemple représentatif. Les nombres dans les colonnes sont fixes; données toujours en lettres simples (mais pas seulement T ou G). le leader peut être n'importe quelle chaîne non nécessairement suivie du nombre de lettres. Le délimiteur sont des onglets. – Jontexas

Répondre

3

awk à la rescousse!

$ awk 'NR%2 {n=split($0,a); next} 
      {for(i=1;i<n;i++) $i=a[i+1] $i; 
      print a[1],$0}' file 

ind1 TT GT TT 
ind2 GG GT TT 

Explication diviser les lignes impaires en colonnes. Fusionner avec la ligne suivante et imprimer. Les lignes paires ont un champ de moins, décaler et imprimer en conséquence.

+0

Parfait! C'est exactement ce que je cherchais, Il est incroyable comment awk est polyvalent pour toute situation hahahahaha – Jontexas

1

solution GNU awk (pour votre entrée en cours):

awk -F'\t' -v FPAT='[^[:space:]]+' 'NF>3{ h=$1; for(i=1;i<=3;i++) a[i]=$(i+1) } 
       NF==3{ print h,a[1]$1,a[2]$2,a[3]$3 }' OFS='\t' file 

La sortie:

ind1 TT GT TT 
ind2 GG GT TT 
+0

Merci @RomanPerekhrest! Cela a fonctionné parfaitement! – Jontexas

2

Une solution non-awk, puisque vous avez demandé des réponses en bash ou python:

cut -f 1-4 -d ' ' in | # the delimiter is a tab here 
    sed 's/^/>/'   | # replace the start of the line with a > 
    while read a b c d # read the fields 
    do if [[ "$a" = '>' ]]      # if > then a second line 
     then printf "$A\t$B$b\t$C$c\t$D$d\t\n" # so stack them 
     else A=${a#'>'}; B=$b; C=$c; D=$d;  # else set for stack later 
     fi 
    done 

Si vous le voulez rapidement pour de grandes quantités de données, j'utiliserais Perl. Ou python.

Ou C. Je déteste awk. Ne pas frapper sa capacité - je ne l'aime pas.

+0

Merci Paul Hodges, mais le problème est qu'il a plus de 150000 champs, donc c'est plus facile sans avoir à définir les champs a-d à lire. Merci beaucoup pour l'explication, je vais probablement l'utiliser pour les fichiers plus petits. – Jontexas

+2

Ensuite, j'utiliserais * définitivement * Perl et je ferais du code dans un repo avec des avertissements et des commentaires stricts et pleins de commentaires. Perl a un peu d'histoire en bioinformatique. –