Perl
perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt
L'idée ici est que nous utilisons l'opérateur modulo %
avec une $.
variable de numéro de ligne , pour déterminer lequel est chaque premier, lequel est chaque seconde et lequel est chaque troisième ligne. Pour chaque 3ème ligne, le reste est 0, tandis que pour chaque 1ère et 2ème ligne, il aura des numéros correspondants.
Tester:
$ cat input.txt
gi_1234
My cat is blue.
I have a cat.
gi_5678
My dog is orange.
I also have a dog.
$ perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt
gi_1234
I have a cat.
My cat is blue.
gi_5678
I also have a dog.
My dog is orange.
Amélioration mineure
L'approche consistant à stocker la deuxième ligne dans une variable présente un défaut. Que faire si la dernière ligne est la "deuxième", c'est-à-dire que pour ce numéro de ligne, le reste est 2? Le code d'origine dans ma réponse et celle de DopeGhoti ne s'imprimera pas My dog is orange
si nous omettons la dernière ligne. La solution pour cela dans les deux cas est d'utiliser un END{}
bloc de code, avec la suppression de la variable temporaire après l'impression. En d'autres termes:
$ awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay;delay=""}END{print delay}' input.txt
et
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s}' input.txt
De cette façon, le code fonctionnera pour un nombre arbitraire de lignes dans un fichier, pas seulement celles divisibles par 3.
Correctif supplémentaire pour le problème mentionné dans les commentaires
Dans le cas de awk, si la dernière ligne du fichier produit une sortie de 1 pour $. % 3, le code précédent a un problème de sortie de la nouvelle ligne vide à cause de l'impression inconditionnelle de END{print delay}
, car la print
fonction mentionnée dans les commentaires ajoute toujours la nouvelle ligne à la variable sur laquelle elle opère. En cas de perl
version, ce problème ne se produit pas, car avec la fonction -ne
drapeaux print
n'ajoute pas la nouvelle ligne.
Néanmoins, le correctif dans le cas d'awk est de rendre conditionnel, comme mentionné par Dope Ghoti dans les commentaires, est de vérifier la longueur de la variable temporaire. La version Perl du même correctif serait:
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s if length $s}' input.txt