
Ich habe eine Datei mit Leerzeilen am Ende. Kann ich grep
die 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 vomH
Befehl 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.//h
Das 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 demh
Befehl, die gesammelten Zeilen auf 1 „zurückzusetzen“. Wenn die nächste leere Zeile angehängt wird, sind es erwartungsgemäß wieder zwei.$!d
stoppt 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
: Derd
Befehl wird erneut nur für nicht leere Zeilen ausgeführt. Wenn die letzte Zeile also nicht leer war,sed
wird er ohne Ausgabe beendet. Null Zeilen. Gut.x
Vertauscht 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 -r
Optionen:
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
/ tac
würde die Datei bei suchbaren Dateien vom Ende her rückwärts lesen). Das ergibt 1
die Ausgabe von printf 'x\n '
.
Antwort4
Da Sie tatsächlich nach einergrep
Lö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 -B
verwenden .|grep -c ".*"
Genial, nicht wahr? (-;