Perl
perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt
La idea aquí es que usamos un operador de módulo %
con una $.
variable de número de línea , para determinar cuál es cada primero, cuál es cada segundo y cuál es cada tercera línea. Para cada tercera línea, el resto es 0, mientras que para cada primera y segunda línea tendrá los números correspondientes.
Prueba:
$ 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.
Mejora menor
El enfoque con el almacenamiento de la segunda línea en una variable tiene un defecto. ¿Qué sucede si la última línea es la "segunda", es decir, para ese número de línea el resto es 2? El código original en mi y la respuesta de DopeGhoti no se imprimirá My dog is orange
si omitimos la última línea. La solución para eso en ambos casos es usar el END{}
bloque de código, desarmando la variable temporal después de imprimir. En otras palabras:
$ awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay;delay=""}END{print delay}' input.txt
y
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s}' input.txt
De esta manera, el código funcionará para un número arbitrario de líneas en un archivo, no solo aquellas divisibles por 3.
Solución adicional para el problema mencionado en los comentarios
En el caso de awk, si la última línea del archivo produce una salida de 1 por $. % 3, el código anterior tiene problemas para generar una nueva línea en blanco debido a la impresión incondicional de END{print delay}
, ya que la print
función mencionada en los comentarios siempre agrega nueva línea a cualquier variable en la que esté operando. En el caso de la perl
versión, este problema no ocurre, ya que con la función -ne
flags print
no se agrega la nueva línea.
Sin embargo, la solución en el caso de awk es hacer condicional, como lo menciona Dope Ghoti en los comentarios, es verificar la longitud de la variable temporal. La versión perl de la misma solución sería:
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s if length $s}' input.txt