Perl
perl -ne 'print if $.%3==1;$var=$_ if $.%3==2;print $_ . $var if $.%3==0' input.txt
Die Idee hier ist, dass wir den Modulo-Operator %
mit der Zeilennummernvariablen verwenden $.
, um herauszufinden, welche jede erste, welche jede Sekunde und welche jede dritte Zeile ist. Für jede 3. Zeile ist der Rest 0, während für jede 1. und 2. Zeile entsprechende Nummern vorhanden sind.
Prüfung:
$ 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.
Kleinere Verbesserung
Der Ansatz mit dem Speichern der zweiten Zeile in einer Variablen weist einen Fehler auf. Was ist, wenn die letzte Zeile die "zweite" ist, dh für diese Zeile ist der Rest 2? Der Originalcode in meiner und DopeGhotis Antwort wird nicht gedruckt, My dog is orange
wenn wir die letzte Zeile weglassen . In beiden Fällen besteht die Lösung darin, einen END{}
Codeblock zu verwenden und die temporäre Variable nach dem Drucken zu deaktivieren. Mit anderen Worten:
$ awk 'NR%3 == 1 { print } NR%3 == 2 { delay=$0 } NR%3 == 0 { print; print delay;delay=""}END{print delay}' input.txt
und
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s}' input.txt
Auf diese Weise funktioniert der Code für eine beliebige Anzahl von Zeilen in einer Datei, nicht nur für die durch 3 teilbaren.
Zusätzlicher Fix für das in den Kommentaren erwähnte Problem
In awks Fall, wenn die letzte Zeile in der Datei eine Ausgabe von 1 für $ ergibt. % 3, der vorherige Code hat das Problem der Ausgabe einer leeren neuen Zeile aufgrund des bedingungslosen Druckens von END{print delay}
, da print
die in den Kommentaren erwähnte Funktion immer eine neue Zeile an die Variable anfügt, mit der er arbeitet. Im Falle einer perl
Version tritt dieses Problem nicht auf, da mit der Funktion -ne
flags print
die Newline nicht angehängt wird.
Nichtsdestotrotz besteht die Lösung in awks Fall darin, bedingt zu machen, wie von Dope Ghoti in den Kommentaren erwähnt, die Länge der temporären Variablen zu überprüfen. Die Perl-Version des gleichen Fixes wäre:
$ perl -ne '$s=$_ if $.%3==2;print $_ . $s and $s="" if $.%3==0 or $.%3==1;END{print $s if length $s}' input.txt