Zählen Sie die Anzahl der Leerzeilen am Ende der Datei

Zählen Sie die Anzahl der Leerzeilen am Ende der Datei

Ich habe eine Datei mit Leerzeilen am Ende. Kann ich grepdie Anzahl der Leerzeilen am Ende der Datei zählen, indem ich den Dateinamen als Variable im Skript übergebe?

Antwort1

Wenn die LeerzeilennurAm Ende

grep  -c '^$' myFile

oder:

grep -cx '' myFile

Antwort2

Nur zum Spaß, etwas gruselig sed:

#!/bin/sh
sed '/./!H;//h;$!d;//d;x;s/\n//' "$1" | wc -l

Erläuterung:

  • /./adressiert Zeilen mit beliebigen Zeichen, /./!adressiert also leere Zeilen (wie /^$/, aber ich möchte das umgekehrte Muster wiederverwenden); diese werden vom HBefehl an den Haltebereich angehängt. Wenn wir also für jede leere Zeile eine Zeile zum Haltebereich hinzugefügt haben, gibt es immer eine Zeile mehr als die Anzahl der leeren Zeilen. Darum kümmern wir uns später.
  • //hDas leere Muster entspricht dem letzten regulären Ausdruck, der ein beliebiges Zeichen war, sodass jede nicht leere Zeile angesprochen wird undgerührtin den Hold-Space mit dem hBefehl, die gesammelten Zeilen auf 1 „zurückzusetzen“. Wenn die nächste leere Zeile angehängt wird, sind es erwartungsgemäß wieder zwei.
  • $!dstoppt das Skript ohne Ausgabe für jede Zeile außer der letzten, sodass weitere Befehle erst nach der letzten Zeile ausgeführt werden. Alle leeren Zeilen, die wir im Hold Space gesammelt haben, stehen also am Ende der Datei. Gut.
  • //d: Der dBefehl wird erneut nur für nicht leere Zeilen ausgeführt. Wenn die letzte Zeile also nicht leer war, sedwird er ohne Ausgabe beendet. Null Zeilen. Gut.
  • xVertauscht Halteraum und Musterraum, so dass die gesammelten Zeilen nun im Musterraum liegen und verarbeitet werden können.
  • Wir merken aber, dass es eine Zeile zu viel ist und reduzieren diese, indem wir mit einen Zeilenumbruch entfernen s/\n//.
  • Voilà! Die Anzahl der Zeilen entspricht der Anzahl der leeren Zeilen am Ende (beachten Sie, dass die erste Zeile nicht leer sein wird, aber wen kümmert das schon), also können wir sie mit zählen wc -l.

Antwort3

Einige weitere GNU tac/ tail -rOptionen:

tac file | awk 'NF{exit};END{print NR?NR-1:0}'

Oder:

tac file | sed -n '/[^[:blank:]]/q;p' | wc -l

Beachten Sie Folgendes bei der Ausgabe:

printf 'x\n '

Das heißt, wenn nach der letzten vollständigen Zeile ein zusätzliches Leerzeichen steht (das manche als zusätzliche Leerzeile betrachten könnten, nach der POSIX-Definition von Text jedoch kein gültiger Text ist), ergibt dies 0.

POSIX:

awk 'NF{n=NR};END{print NR-n}' < file

das bedeutet aber, dass die Datei vollständig gelesen werden muss ( tail -r/ tacwürde die Datei bei suchbaren Dateien vom Ende her rückwärts lesen). Das ergibt 1die Ausgabe von printf 'x\n '.

Antwort4

Da Sie tatsächlich nach einergrepLösungIch füge Folgendes hinzu, wobei ich mich ausschließlich auf GNU stütze grep(okay, ich verwende auch Shell-Syntax und echo...):

#!/bin/sh
echo $(( $(grep -c "" "$1") - $(grep -B$(grep -cv . "$1") . "$1" |grep -c "") ))

Was mache ich hier? $(grep -c ".*" "$1")Wir zählen alle Zeilen in der Datei und subtrahieren dann die Datei ohne die nachfolgenden Leerzeilen.

Und wie bekommt man diese? Es $(grep -B42 . "$1"würde alle nicht leeren Zeilen und die 42 Zeilen davor greppen, sodass es alles bis zur letzten nicht leeren Zeile ausdrucken würde, solange nicht mehr als 42 aufeinanderfolgende leere Zeilen vor einer nicht leeren Zeile stehen. Um diese Beschränkung zu umgehen, nehme ich $(grep -cv . "$1")als Parameter für die Option die Gesamtzahl der leeren Zeilen, also immer groß genug. Auf diese Weise habe ich die nachfolgenden leeren Zeilen entfernt und kann sie zum Zählen der Zeilen -Bverwenden .|grep -c ".*"

Genial, nicht wahr? (-;

verwandte Informationen