Eu tenho vários arquivos, ou seja SRR3384742.Gene.out.tab
SRR3384743.Gene.out.tab
SRR3384744.Gene.out.tab
, muitos mais nessa ordem. Estou extraindo a primeira e a quarta colunas desses arquivos e armazeno em um arquivo de saída. Estou tentando garantir que, quando meu script lê um novo arquivo, ele extraia a maneira separada da guia de dados, em vez de os dados serem anexados no final de cada arquivo.
Arquivos de entrada:
SRR3384742.Gene.out.tab
N_unmapped 313860 313860 313860
N_multimapping 5786679 5786679 5786679
N_noFeature 286816 31696770 438410
N_ambiguous 1283487 32117 65902
AT1G01010 301 0 301
AT1G01020 623 1 622
AT1G03987 5 5 0
AT1G01030 151 2 149
SRR3384743.Gene.out.tab
N_unmapped 780346 780346 780346
N_multimapping 4621162 4621162 4621162
N_noFeature 182428 28470016 362650
N_ambiguous 1451612 43059 117293
AT1G01010 154 3 151
AT1G01020 685 2 683
AT1G03987 0 0 0
AT1G01030 63 0 63
Saída que estou recebendo:
SRR3384742.Gene.out.tab
AT1G01010 301
AT1G01020 622
AT1G03987 0
AT1G01030 149
SRR3384743.Gene.out.tab
AT1G01010 151
AT1G01020 683
AT1G03987 0
AT1G01030 63
Saída desejada:
SRR3384742.Gene.out.tab SRR3384743.Gene.out.tab
AT1G01010 301 151
AT1G01020 622 683
AT1G03987 0 0
AT1G01030 149 63
Tentei o seguinte script:
for sample in *Gene.out.tab; do echo -en $sample "\n"; awk 'NR>4 {print $1 "\t" $4}' $sample; awk '{print $0, $sample}' OFS='\t' $sample; done > output
Isso deve fornecer a saída descrita nos comentários, usando GNU
awk
:E, para deixar tudo bem alinhado visualmente, passe por
column
:FNR
é uma variável awk especial que sempre contém o número da linha do arquivo atual que está sendo processado.FILENAME
é uma variável especial GNUawk
que contém o nome do arquivo que está sendo processado no momento.FNR==1{names[c++]=FILENAME}
: se esta for a primeira linha de um dos arquivos de entrada, use a variávelc
como índice para onames
array cujos valores são os nomes dos arquivos e também incremente seu valor yb 1 (c++
). Depois que todos os arquivos forem processados,files[0]
será o primeiro nome do arquivo,files[1]
será o segundo e assim por diante.FNR>4{ lines[$1] = "x"lines[$1] ? lines[$1]"\t"$4 : $4; }
: Isso é equivalente a isso:Se o número da linha do arquivo de entrada atual for 5 ou mais, verifique se este primeiro campo possui um valor associado no array
lines
. Verificamos usando"x"lines[$i]
porque selines[$1]
is0
, então o teste seria falso, masx0
é verdadeiro, então ox
protege disso. Portanto, se tivermos um valor, anexaremos uma guia e o 2º campo da linha atual a ele, e se não tivermos um valor, definimos como o 4º campo da linha atual.END{ ... }
: faça isso depois de processar todas as entradas.for(i=0;i<=c;i++){printf "\t%s",names[i]}; printf "\n";
: imprime cada nome de arquivo nonames
array, precedido por uma tabulação. Queremos que a guia principal garanta que tenhamos o mesmo número de campos nas linhas de cabeçalho e no conteúdo. Depois de imprimir os nomes dos arquivos, imprima uma nova linha.for(i in lines){print i,lines[i]}
: para cada índice dolines
array, imprima o índice (o ID) e depois imprima o valor associado que foi armazenado na primeira etapa.Limitação : isso requer o armazenamento de todos os dados de saída na memória. Isso realmente não deve ser um problema em máquinas modernas, já que armazenamos apenas os IDs e apenas um valor por ID por arquivo, portanto, deve ser capaz de lidar com enormes quantidades de entrada antes de bloquear em uma máquina razoavelmente decente, mas pode se tornar um problema com quantidades realmente enormes de dados.
Usar
join
Usar
paste
Acho que
paste
é o que você procura:Esta solução pressupõe que todos
*.tab
devem ter:Aqui está um script que imprime cabeçalhos e processa vários arquivos:
resultado