Como repetir uma linha para cada valor de sua coluna correspondente

1

eu não sou especialista em programação, eu quero repetir uma linha para todos os seus valores correspondentes qualquer ajuda

meu arquivo de entrada é assim

    pos     COL1  COL2  COL3
    18691441    C   A   G
    18691572    G   C   G
    18691620    A   T   G
    18691716    C   G   C

eu quero saída como esta

pos COL1    
18691441    COL1 C  
18691441    COL2 A  
18691441    COL3 G  
18691572    COL1 G  
18691572    COL2 C  
18691572    COL3 G  
18691620    COL1 A  
18691620    COL2 T  
18691620    COL3 G  
18691716    COL1 C  
18691716    COL2 G  
18691716    COL3 C

Eu estou tentando repetir uma linha, mas isso simplesmente faz com que eles sejam duplicados, estou usando

while read line; do for i in {1..3}; do echo "$line"; done; done < real2.txt

e dá saída:

pos       COL1 COL2 COL3
18691441    C   A   G
18691441    C   A   G
18691441    C   A   G
18691572    G   C   G
18691572    G   C   G
18691572    G   C   G
18691620    A   T   G
18691620    A   T   G
18691620    A   T   G
18691716    C   G   C
18691716    C   G   C
18691716    C   G   C

então eu extraí o pos do arquivo 1.txt de entrada e faço 1_pos.txt e escrevo algo assim:

     pos
    18691441
    18691572
    18691620
    18691716
    for i in 'cat 1_post.txt';
    do
   x=$(grep -i "^$i" 1.txt | awk 'FNR == 1 {print $1"\t""COL1""\t"$2}' ) ;
   y=$(grep -i "^$i" 1.txt | awk 'FNR == 1 {print $1"\t""COL2""\t"$3}' ) ;
   z=$(grep -i "^$i" 1.txt | awk 'FNR == 1 {print $1"\t""COL3""\t"$4}' ) ;

    echo -e "$x""\n""$y""\n""$z";
    done  

isso me dá saída, com informações de coluna, mas e se eu tiver 405 colunas em vez de três eu não quero repetir linhas para cada coluna 405 vezes, eu tento colocar isso em loop, mas não funciona, qualquer ajuda pessoal:

18691441    COL1    C
18691441    COL2    A
18691441    COL3    G
18691572    COL1    G
18691572    COL2    C
18691572    COL3    G
18691620    COL1    A
18691620    COL2    T
18691620    COL3    G
18691716    COL1    C
18691716    COL2    G
18691716    COL3    C
    
por a.k 10.05.2017 / 09:18

4 respostas

2

Que tal:

while read line col1 col2 col3; 
do 
    if [[ "$line" = "pos" ]]; then
        echo "pos COL"
        continue    
    fi
    echo "$line COL1 $col1"  
    echo "$line COL2 $col2"  
    echo "$line COL3 $col3"  
done < real2.txt

saída:

pos COL
18691441 COL1 C
18691441 COL2 A
18691441 COL3 G
18691572 COL1 G
18691572 COL2 C
18691572 COL3 G
18691620 COL1 A
18691620 COL2 T
18691620 COL3 G
18691716 COL1 C
18691716 COL2 G
18691716 COL3 C
    
por 10.05.2017 / 10:12
2

awk abordagem:

awk 'BEGIN{OFS="\t";print "pos" OFS "COL1"}{if(NR==1){for(f=2;f<=NF;f++) c[f]=$f;}
     else{for(i=2;i<=NF;i++) print $1,c[i],$i}}' real2.txt

A saída:

pos     COL1
18691441        COL1    C
18691441        COL2    A
18691441        COL3    G
18691572        COL1    G
18691572        COL2    C
18691572        COL3    G
18691620        COL1    A
18691620        COL2    T
18691620        COL3    G
18691716        COL1    C
18691716        COL2    G
18691716        COL3    C

OFS="\t" - separador de campo de saída

print "pos" OFS "COL1" - imprime cabeçalho linha

if(NR==1){for(f=2;f<=NF;f++) c[f]=$f; - coletando nomes de coluna da primeira / linha de cabeçalho

for(i=2;i<=NF;i++) print $1, c[i], $i - imprimindo cada coluna ( COL... ) valor "rowwise" em relação ao respectivo valor da coluna pos e seu nome de coluna correspondente.

    
por 10.05.2017 / 09:25
2

Não use loops de shell para processar texto.

Aqui, awk é a ferramenta certa para a tarefa. Mas você só precisa ligar uma vez:

awk -v OFS='\t' '
  NR == 1 {print $1, "name", "value"; split($0, header); next}
  {for (i = 2; i < NF; i++) print $1, header[i], $i}' < your-file

(uma variação da resposta de Roman )

    
por 10.05.2017 / 14:14
1
while IFS= read -r l; do
   read -r -a A <<<"$l"
   case $l in
      'pos'[\ \   ]* )
         echo "${A[@]:0:2}"
         C=("${A[@]:1}")
         ;;

      * )
         p=0 x=${A[0]}
         for e in "${A[@]:1}"; do
            echo "$x ${C[$p]} $e"
            ((p++))
         done
         ;;
   esac
done < yourfile


sed -E '
   /\n/bloop

   y/\t/ /;s/  +/ /g;s/^ +//;s/ +$//

   1{
      h
         s/ /\n/2
      x
         s/ /\n/;s/.*\n//
      x
         s/\n.*//
      b
   }

   G;s/\n/ &/

   :loop
      #  1     2     3   4   5
      s/^(\S+ )(\S+) (.*)(\n)(\S+) ?/ /
      /\n$/{
         /\n.*\n/!d
      }
       P
      /\n.*\n/D
   tloop

' yourfile

Resultados

pos COL1
18691441 COL1 C
18691441 COL2 A
18691441 COL3 G
18691572 COL1 G
18691572 COL2 C
18691572 COL3 G
18691620 COL1 A
18691620 COL2 T
18691620 COL3 G
18691716 COL1 C
18691716 COL2 G
18691716 COL3 C

Explicação

  • Primeiramente, nós convertemos quaisquer TABs residuais em espaços, em seguida, comprimimos vários espaços e, por fim, ajustamos os espaços iniciais / finais.
  • Fazemos um tratamento especial da primeira linha:
    • a) faça uma cópia da linha.
    • b) marque o final da segunda coluna para mais tarde.
    • c) trocar esta linha marcada com a cópia armazenada no espaço de espera.
    • d) tira a primeira coluna, depois volta & nessa exibição cols1,2.
  • Para todas as outras linhas, (2 a eof), acrescentamos os nomes das colunas à linha.
  • Em seguida, configure um loop do-while no qual, em cada iteração, reorganizamos os campos da maneira mostrada, para que o nome da coluna junto com seu valor seja impresso. Paramos quando vemos uma linha tendo \n no final E é a única \n char restante na linha. Caso contrário, apenas cortamos a parte de ataque e desviamos para o início do loop.
por 10.05.2017 / 10:30

Tags