Perl
perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt
A idéia aqui é que usamos o operador de módulo %
com o número de linha $.
variable, para descobrir qual é a primeira, qual é a cada segundo e qual é a cada terceira linha. Para cada 3ª linha, o resto é 0, enquanto para cada 1ª e 2ª linha, terá os números correspondentes.
Teste:
$ 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.
Melhoria menor
A abordagem com o armazenamento da segunda linha em uma variável tem uma falha. E se a última linha for a "segunda", ou seja, para esse número de linha o restante é 2? O código original na resposta do meu e do DopeGhoti não imprimirá My dog is orange
se deixarmos de fora a última linha. A correção para isso nos dois casos é usar o bloco de código END{}
, com a desativação da variável temporária após a impressão. Em outras palavras:
$ awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay;delay=""}END{print delay}' input.txt
e
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s}' input.txt
Dessa forma, o código funcionará para um número arbitrário de linhas em um arquivo, não apenas aquelas divisíveis por 3.
Correção adicional para problemas mencionados nos comentários
No caso do awk, se a última linha do arquivo produzir uma saída de 1 para $. % 3, o código anterior tem problema de gerar uma nova linha em branco devido à impressão incondicional de END{print delay}
, pois a função print
mencionada nos comentários sempre anexa nova linha a qualquer variável em que esteja operando. No caso de perl
versão, esse problema não ocorre, pois com -ne
flags print
function não acrescenta a nova linha.
No entanto, a correção no caso do awk é tornar condicional, como mencionado por Dope Ghoti nos comentários é para verificar o tamanho da variável temporária. A versão perl da mesma correção seria:
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s if length $s}' input.txt