Perl
perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt
Chodzi o to, że używamy operatora modulo %
ze $.
zmienną numeru linii , aby dowiedzieć się, który z nich jest co pierwszy, a który co sekundę, a który co 3 linię. Dla każdej trzeciej linii pozostała wartość wynosi 0, natomiast dla każdej pierwszej i drugiej linii będzie mieć odpowiadające jej liczby.
Test:
$ 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.
Niewielka poprawa
Podejście polegające na przechowywaniu drugiej linii w zmiennej ma wadę. Co jeśli ostatni wiersz to „drugi”, tzn. Dla tego numeru reszta to 2? Oryginalny kod w mojej i DopeGhoti odpowiedzi nie zostanie wydrukowany, My dog is orange
jeśli pominiemy ostatni wiersz. Rozwiązaniem tego problemu w obu przypadkach jest użycie END{}
bloku kodu z rozbrajaniem zmiennej tymczasowej po wydrukowaniu. Innymi słowy:
$ awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay;delay=""}END{print delay}' input.txt
i
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s}' input.txt
W ten sposób kod będzie działał dla dowolnej liczby wierszy w pliku, nie tylko tych podzielnych przez 3.
Dodatkowa poprawka dotycząca problemu wymienionego w komentarzach
W przypadku awk, jeśli ostatni wiersz w pliku daje wynik 1 dla $. % 3, poprzedni kod miał problem z wyświetlaniem pustego znaku nowej linii z powodu bezwarunkowego drukowania END{print delay}
, ponieważ print
funkcja wymieniona w komentarzach zawsze dołącza znak nowej linii do dowolnej zmiennej, na której działa. W przypadku perl
wersji ten problem nie występuje, ponieważ funkcja z -ne
flagami print
nie dołącza nowego wiersza.
Niemniej jednak poprawką w przypadku awk jest uzależnienie, jak wspomniał Dope Ghoti w komentarzach, aby zweryfikować długość zmiennej tymczasowej. Wersja tej samej poprawki dla Perla to:
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s if length $s}' input.txt