Wie drucke ich alle bis auf die n-te bis letzte Zeile in sed?

9
  • Ich würde gerne das Komplement / "Gegenteil" von machen

    sed 13q;d <file.txt
    

    Ist es allgemeiner möglich, diese Art von Komplement / Inverse / Gegenteil in zu machen sed? Oder nur für Regexe?

  • Wie drucke ich alle bis auf die vorletzte Zeile? Benötigt dies zwei tacund zählt vorwärts sed? Oder gibt es eine Möglichkeit, sedsich von hinten zählen zu lassen?

Isomorphismen
quelle

Antworten:

12

Teil 1

dGeben Sie einfach die 13. Zeile ein:

sed '13d' <file.txt

Ein allgemeiner Weg, um das oben Genannte zu ergänzen, ist:

sed '13!d' <file.txt

Teil 2

Weil es möglich ist:

sed -n ':a;${P;q};N;4,$D;ba' <file.txt

Beachten 4Sie, dass dies eine Nummer mehr ist als die von Ihnen benötigte Nummer. Wenn Sie also die letzte bis zehnte Zeile wollten, wäre dies 11.

Testen mit seq:

$ seq 100 | sed -n ':a;${P;q};N;4,$D;ba'
98
$ 

Versuchte Erklärung

:a        # define label a
${        # match the last line
    P     # print the first line of the pattern space
    q     # quit
}
N         # match all lines: append the next line to the pattern
4,${      # match the range of lines 4 to the end of the file
    D     # delete the first line of the pattern space
}
ba        # match all lines: jump back to label a 

Glenn Jackmans wertvolle Ergänzung:

Das war "nur die N-te Zeile". Hier ist "alles ABER die N-te Zeile":

sed -n ':a;${s/^[^\n]*\n//;p;q};N;4,${P;D};ba'

funktioniert mit GNU sed, die \nSequenz funktioniert möglicherweise nicht mit anderen seds.


Ich habe dies mit BSD sed (OSX) versucht und festgestellt, dass es in der obigen Form nicht ganz funktioniert hat. Die Probleme scheinen zu sein:

  1. ; Das Trennen von Zeilen scheint im Allgemeinen zu funktionieren, funktioniert jedoch nach einer Beschriftung nicht
  2. BSD sed scheint ;nach dem letzten Befehl in einer einzeiligen {}Befehlsgruppe erforderlich zu sein , während GNU sed dies nicht tut
  3. \nkann im Allgemeinen innerhalb des regulären Ausdrucks verwendet werden, aber anscheinend nicht innerhalb eines []Klammerausdrucks. Um Zeilenumbrüche auszuschließen, können wir [[:alnum:][:punct:][:graph:][:blank:]]stattdessen so etwas wie verwenden, obwohl dies andere Zeichen (insbesondere andere Steuerzeichen) ausschließen kann.

Dies ist also ein Versuch einer plattformunabhängigeren Version:

sed -n ':a
${s/^[[:alnum:][:punct:][:graph:][:blank:]]*\n//p;q;};N;4,${P;D;};ba'

Dies scheint unter OSX und Ubuntu zu funktionieren.

Digitales Trauma
quelle
@jimmij Die anderen Antworten zu verwandten Fragen im SE-Netzwerk legen nahe, dass eine head/ tail-Lösung viel langsamer ist als eine sedLösung. Trotzdem danke.
Isomorphismen
3
@isomorphismes Kein Programm kann die Anzahl der Zeilen in einer Datei kennen, es sei denn, es durchläuft die gesamte Datei. Daran führt kein Weg vorbei. Die einzige Möglichkeit, von unten zu zählen, besteht darin, entweder die Datei umzukehren und von oben zu zählen oder sie zweimal zu analysieren. Kopf / Schwanz werden also so schnell wie möglich sein.
Terdon
@isomorphismes ... weil sie ( head/ tail) für das optimiert sind, was sie tun.
Peterph
@ Isomorphismes - bearbeitet mit allen Teilen, die Sie benötigen
Digital Trauma
Nett! Ich musste meine Antwort ändern, da ich irgendwie erwartet hatte, dass es komplizierter wird. :)
Peterph