web-dev-qa-db-fra.com

Comment insérer un en-tête différent pour chaque ligne avec sed?

J'ai besoin de modifier un fichier texte avec 770 lignes et d'ajouter un en-tête différent pour chacune d'elles, par exemple, j'ai ceci:

CWGAGATCGGAAGAGCGGTTCAGCAGGAATGCCGAG
ACACTCTTTCCCTACACGACGCTCTTCCGATCTAGGC
ACACTCTTTCCCTACACGACGCTCTTCCGATCTGATT
ACACTCTTTCCCTACACGACGCTCTTCCGATCTACCGT

Et je veux obtenir ceci:

>seq1
CWGAGATCGGAAGAGCGGTTCAGCAGGAATGCCGAG
>seq2
ACACTCTTTCCCTACACGACGCTCTTCCGATCTAGGC
>seq3
ACACTCTTTCCCTACACGACGCTCTTCCGATCTGATT
>seq4
ACACTCTTTCCCTACACGACGCTCTTCCGATCTACCGT
7
Idalia Rojas

Puisque vous avez spécifiquement demandé une solution sed (je ne suggérerais pas de le faire de cette façon, mais vous pourriez le faire):

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

La première invocation sed = file insère des numéros de ligne nue, puis la seconde décore celle-ci en ajoutant la chaîne >seq.


OTOH si vous savez à l’avance qu’il ya 770 lignes, vous pouvez le faire.

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

bien que cela repose sur l'extension GNU sed R:

R nom de fichier
Met en file d'attente une ligne de nom de fichier à lire et à insérer dans le flux de sortie à la fin du cycle en cours ou lors de la lecture de la ligne suivante. Notez que si le nom de fichier ne peut pas être lu, ou si sa fin est atteinte, aucune ligne n'est ajoutée, sans aucune indication d'erreur.

Bien sûr, si vous ne connaissez pas le nombre de lignes à l’avance, vous pourriez faire

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

mais cela perdrait l'avantage de n'avoir besoin que de lire le fichier une fois.


En pratique, j'utiliserais probablement la solution awk de @ John1024 ou son équivalent en Perl

Perl -lpe 'print ">seq" . $.' file
13
steeldriver

Votre tâche peut être accomplie avec sed, mais sed ne possède aucune compréhension native de l'arithmétique, ce qui en fait un mauvais outil. Awk fonctionne bien:

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

Comment ça fonctionne:

  • print ">seq" NR

    Pour chaque nouvelle ligne lue, nous imprimons d’abord l’en-tête souhaité.

    NR est le compteur de lignes de awk.

  • 1

    C'est le raccourci d'awk pour print-the-line.

12
John1024

En utilisant une simple boucle:

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

Le résultat:

>seq1
CWGAGATCGGAAGAGCGGTTCAGCAGGAATGCCGAG
>seq2
ACACTCTTTCCCTACACGACGCTCTTCCGATCTAGGC
>seq3
ACACTCTTTCCCTACACGACGCTCTTCCGATCTGATT
>seq4
ACACTCTTTCCCTACACGACGCTCTTCCGATCTACCGT
5
Ravexina

Utiliser paste:

 paste -d '\n' <(seq -f '>seq%g' 1 4) file
  • seq -f '>seq%g' 1 4 écrit les numéros séparés par une nouvelle ligne sur la sortie standard
  • <(...) est la substitution de processus
  • paste concatène la ligne correspondante de chaque fichier, séparée par un délimiteur
  • -d '\n' définit le délimiteur de concaténation sur une nouvelle ligne au lieu de l'onglet par défaut
0
gardenhead