Como inserir um cabeçalho diferente para cada linha com sed?

7

Eu preciso modificar um arquivo de texto com 770 linhas, e adicionar um cabeçalho diferente para cada um deles, por exemplo, eu tenho isso:

CWGAGATCGGAAGAGCGGTTCAGCAGGAATGCCGAG
ACACTCTTTCCCTACACGACGCTCTTCCGATCTAGGC
ACACTCTTTCCCTACACGACGCTCTTCCGATCTGATT
ACACTCTTTCCCTACACGACGCTCTTCCGATCTACCGT

E eu quero obter isso:

>seq1
CWGAGATCGGAAGAGCGGTTCAGCAGGAATGCCGAG
>seq2
ACACTCTTTCCCTACACGACGCTCTTCCGATCTAGGC
>seq3
ACACTCTTTCCCTACACGACGCTCTTCCGATCTGATT
>seq4
ACACTCTTTCCCTACACGACGCTCTTCCGATCTACCGT
    
por Idalia Rojas 18.08.2017 / 21:43

4 respostas

13

Desde que você solicitou especificamente uma solução sed (eu não sugeriria que fosse feito dessa maneira - mas você poderia):

$ sed = file | sed '1~2 s/^/>seq/'
>seq1
CWGAGATCGGAAGAGCGGTTCAGCAGGAATGCCGAG
>seq2
ACACTCTTTCCCTACACGACGCTCTTCCGATCTAGGC
>seq3
ACACTCTTTCCCTACACGACGCTCTTCCGATCTGATT
>seq4
ACACTCTTTCCCTACACGACGCTCTTCCGATCTACCGT

A primeira invocação sed = file insere números de linha simples, depois a segunda decora a frase preponderante >seq .

OTOH se você sabe antecipadamente que existem 770 linhas, então você poderia fazer

printf ">seq%d\n" {1..770} | sed 'R file'

embora isso dependa da extensão sed R do GNU:

  

R nome do arquivo
  Fila uma linha de nome de arquivo a ser lido e inserido na saída   fluxo no final do ciclo atual, ou quando a próxima linha de entrada é   ler. Note que se filename não puder ser lido, ou se o seu final for alcançado,   nenhuma linha é anexada, sem qualquer indicação de erro.

Claro que se você não souber o número de linhas antes do tempo, você poderá fazer

printf ">seq%d\n" $(seq 1 "$(wc -l < file)") | sed 'R file'

mas isso perderia a vantagem de precisar ler o arquivo apenas uma vez.

Na prática, eu provavelmente usaria a @ solução de awk do John1024 ou seu equivalente em perl

perl -lpe 'print ">seq" . $.' file
    
por steeldriver 18.08.2017 / 21:56
12

Sua tarefa pode ser executada com sed, mas sem qualquer compreensão nativa de aritmética, o que torna a ferramenta errada. Awk funciona bem:

$ awk '{print ">seq" NR} 1' file
>seq1
CWGAGATCGGAAGAGCGGTTCAGCAGGAATGCCGAG
>seq2
ACACTCTTTCCCTACACGACGCTCTTCCGATCTAGGC
>seq3
ACACTCTTTCCCTACACGACGCTCTTCCGATCTGATT
>seq4
ACACTCTTTCCCTACACGACGCTCTTCCGATCTACCGT

Como funciona:

  • print ">seq" NR

    Para cada nova linha lida, primeiro imprimimos o cabeçalho que você deseja.

    NR é o contador de linha do awk.

  • 1

    Esta é uma abreviada enigmática do awk para imprimir a linha.

por John1024 18.08.2017 / 21:48
5

Usando um loop simples:

count=1; while read -r line ; do printf '>seq%d\n%s\n' $((count++)) "$line"; done < file

A saída:

>seq1
CWGAGATCGGAAGAGCGGTTCAGCAGGAATGCCGAG
>seq2
ACACTCTTTCCCTACACGACGCTCTTCCGATCTAGGC
>seq3
ACACTCTTTCCCTACACGACGCTCTTCCGATCTGATT
>seq4
ACACTCTTTCCCTACACGACGCTCTTCCGATCTACCGT
    
por Ravexina 18.08.2017 / 21:54
0

Usando paste :

 paste -d '\n' <(seq -f '>seq%g' 1 4) file
  • seq -f '>seq%g' 1 4 escreve números separados por nova linha para stdout
  • & lt; (...) é a substituição do processo
  • paste concatena a linha correspondente de cada arquivo, separada por um delimitador
  • -d '\n' define o delimitador de concatenação como uma nova linha em vez da guia padrão
por gardenhead 18.08.2017 / 23:58