Perl
perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt
Идея здесь в том, что мы используем оператор по модулю %
с $.
переменной номера строки , чтобы выяснить, какой из них является первым, какой - каждой второй, а какой - каждой третьей строкой. Для каждой третьей строки остаток равен 0, а для каждой 1-й и 2-й строки он будет иметь соответствующие номера.
Тестовое задание:
$ 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? Исходный код в ответах my и 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
flags print
не добавляет символ новой строки.
Тем не менее, исправление в случае с awk состоит в том, чтобы сделать его условным, как упомянул Dope Ghoti в комментариях, чтобы проверить длину временной переменной. Версия того же исправления для 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