Perl
perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt
Ідея тут полягає в тому, що ми використовуємо оператор модуля %зі $.змінною номера рядка , щоб визначити, який з них кожен перший, який - кожен другий, а який - кожен 3-й рядок. Для кожного третього рядка залишок дорівнює 0, тоді як для кожного першого та другого рядків він матиме відповідні номери.
Тест:
$ 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.
Незначне вдосконалення
Підхід із збереженням другого рядка у змінній має недолік. Що робити, якщо останній рядок є "другим", тобто для останнього номера рядка дорівнює 2? Оригінальний код у моїй відповіді та DopeGhoti не надрукується, My dog is orangeякщо ми не залишимо останній рядок. Виправленням цього в обох випадках є використання END{}кодового блоку з відміною тимчасової змінної після друку. Іншими словами:
$ awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay;delay=""}END{print delay}' input.txt
і
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s}' input.txt
Таким чином, код буде працювати для довільної кількості рядків у файлі, а не тільки для тих, що діляться на 3.
Додаткове виправлення до проблеми, згаданої в коментарях
У випадку awk, якщо останній рядок у файлі дає вихід 1 за $. % 3, попередній код випустив порожній новий рядок через безумовну друк END{print delay}, оскільки printфункція, зазначена в коментарях, завжди додає новий рядок до будь-якої змінної, на якій він працює. У разі perlверсії цього питання не виникає, оскільки функція -neпрапорів printне додає новий рядок.
Тим не менш, виправлення у випадку awk полягає в тому, щоб зробити умовою, як згадує Допі Готі в коментарях, - це перевірити довжину тимчасової змінної. Версія Perl того ж виправлення буде:
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s if length $s}' input.txt