Concatena vários arquivos com o mesmo cabeçalho

23

Eu tenho vários arquivos com o mesmo cabeçalho e vetores diferentes abaixo. Eu preciso concatenar todos eles, mas quero apenas que o cabeçalho do primeiro arquivo seja concatenado e não quero que outros cabeçalhos sejam concatenados, já que são todos iguais.

por exemplo: arquivo1.txt

<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
A
B 
C

arquivo2.txt

<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
D
E 
F

Eu preciso que a saída seja

<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
A
B
C
D
E 
F

Eu poderia escrever um script em R, mas preciso dele no shell?

    
por Jana 07.01.2013 / 22:39

6 respostas

15

Se você sabe como fazer isso em R, então faça isso em R. Com ferramentas clássicas de unix, isso é feito naturalmente no awk.

awk '
    FNR==1 && NR!=1 { while (/^<header>/) getline; }
    1 {print}
' file*.txt >all.txt

A primeira linha do script awk corresponde à primeira linha de um arquivo ( FNR==1 ), exceto se também for a primeira linha em todos os arquivos ( NR==1 ). Quando essas condições são atendidas, a expressão while (/^<header>/) getline; é executada, o que faz com que o awk continue lendo outra linha (pulando a atual) desde que a atual corresponda à regexp ^<header> . A segunda linha do script awk imprime tudo, exceto as linhas que foram ignoradas anteriormente.

    
por 08.01.2013 / 01:03
35

Outra solução, semelhante a " cat+grep " acima, usando tail e head :

  1. Escreva o cabeçalho do primeiro arquivo na saída:

    head -2 file1.txt > all.txt
    

    - head -2 obtém 2 primeiras linhas do arquivo.

  2. Adicione o conteúdo de todos os arquivos:

    tail -n +3 -q file*.txt >> all.txt
    

    - -n +3 faz com que tail imprima linhas do 3º ao fim, -q diz para não imprimir o cabeçalho com o nome do arquivo (leia man ), >> adiciona ao arquivo, não sobrescreve como > .

E com certeza você pode colocar os dois comandos em uma linha:

head -2 file1.txt > all.txt; tail -n +3 -q file*.txt >> all.txt

ou em vez de ; colocar && entre eles para verificação de sucesso.

    
por 30.11.2014 / 16:21
4

Tente fazer isso:

$ cat file1.txt; grep -v "^<header" file2.txt
<header>INFO=<ID=DP,Number=1,Type=Integer>
<header>INFO=<ID=DP4,Number=4,Type=Integer>
A
B 
C
D
E 
F

NOTA

  • a sinalização -v significa que a correspondência de foi invertida
  • ^ em REGEX , significa início da string
  • se você tiver vários arquivos, poderá fazer

:

array=( files*.txt )
{ cat ${array[@]:0:1}; grep -v "^<header" ${array[@]:1}; } > new_file.txt

É uma técnica de corte de matriz .

    
por 07.01.2013 / 22:43
1

O comando tail (no GNU, pelo menos) tem uma opção para pular um determinado número de linhas iniciais. Para imprimir a partir da segunda linha, ou seja, pular um cabeçalho de uma linha, faça: tail -n+2 myfile

Então, para manter o cabeçalho de duas linhas do primeiro arquivo, mas não o segundo, no Bash:

cat file1.txt <(tail -n+3 file2.txt) > combined.txt

Ou, para muitos arquivos:

head -n1 file1.txt > combined.txt
for fname in *.txt
do
    tail -n+3 $fname >> combined.txt
done

Se uma determinada string estiver presente em todas as linhas de cabeçalho, mas nunca no restante dos arquivos de entrada, grep -v é uma abordagem mais simples, como o sputnik mostrou.

    
por 24.02.2014 / 07:23
1

Mais curto (não necessariamente mais rápido) com sed :

sed -e '3,${/^<header>/d' -e '}' file*.txt > all.txt

Isso excluirá todas as linhas que começam com <header>... a partir da linha 3, para que o primeiro cabeçalho seja preservado e os outros cabeçalhos sejam removidos. Se houver um número diferente de linhas no cabeçalho, ajuste o comando de acordo (por exemplo, para o cabeçalho de 6 linhas, use 7 em vez de 3 ).
Se o número de linhas no cabeçalho for desconhecido, você poderia tentar assim:

sed '1{
: again
n
/^<header>/b again
}
/^<header>/d
' file*.txt > all.txt
    
por 10.01.2016 / 13:42
0

array=( *.txt );head -1 ${array[0]} > all.txt; tail -n +2 -q ${array[@]:0} >> all.txt

Supondo que você esteja usando uma pasta com arquivos .txt com o mesmo cabeçalho que precisa ser combinado / concatenado, esse código combinaria todos os arquivos txt em all.txt com apenas um cabeçalho. a primeira linha (linhas separadas por ponto e vírgula) reúne todos os arquivos de texto para concatenar, as segundas linhas geram o cabeçalho do primeiro arquivo txt em all.txt e a última linha concatena todos os arquivos de texto reunidos sem o cabeçalho (iniciando a concatenação da linha 2 em diante) e anexando-o a all.txt .

    
por 24.12.2015 / 16:44