Ich habe eine Datei mit Leerzeilen am Ende der Datei. Kann ich grep
die Anzahl der Leerzeilen am Ende der Datei zählen, wobei der Dateiname im Skript als Variable übergeben wird?
text-processing
grep
wc
Raghunath Choudhary
quelle
quelle
grep
@MichaelJohn gewinnt für Reinheit in meinem Buch.Antworten:
Wenn die Leerzeilen nur am Ende stehen
oder:
quelle
grep -cv . myFile
ist eine andere Art, es zu schreiben (für Code-Golfer). Aber ich habe eine Lösung gefunden,grep
wenn es irgendwo in der Datei leere Zeilen gibt.grep -cv .
würde auch die Zeilen zählen, die nur Bytes enthalten, die keine gültigen Zeichen bilden.Nur zum Spaß, einige gruselig
sed
:Erläuterung:
/./
adressiert Zeilen mit einem beliebigen Zeichen,/./!
adressiert also nicht leere Zeilen; Für dieseH
hängt der Befehl sie an den Haltebereich an. 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. Wir werden uns später darum kümmern.//h
Das leere Muster entspricht dem letzten regulären Ausdruck, bei dem es sich um ein beliebiges Zeichen handelt. Daher wird jede nicht leere Zeile adressiert und durch den Befehl in den Haltebereich verschoben , umh
die gesammelten Zeilen auf 1 zurückzusetzen. Wenn die nächste leere Zeile angehängt wird, Wie erwartet wird es wieder zwei geben.$!d
Stoppt das Skript ohne Ausgabe für jede bis auf die letzte Zeile, sodass weitere Befehle erst nach der letzten Zeile ausgeführt werden. Alle leeren Zeilen, die wir im Haltebereich gesammelt haben, befinden sich am Ende der Datei. Gut.//d
: Derd
Befehl wird erneut nur für nicht leere Zeilen ausgeführt. Wenn also die letzte Zeile nicht leer war,sed
wird sie ohne Ausgabe beendet. Nulllinien. Gut.x
Der Austausch enthält Speicherplatz und Musterraum, sodass sich die gesammelten Zeilen im Musterraum befinden, der jetzt verarbeitet werden soll.s/\n//
.wc -l
.quelle
Einige weitere GNU
tac
/tail -r
Optionen:Oder:
Beachten Sie, dass auf der Ausgabe von:
Das heißt, wenn nach der letzten vollständigen Zeile ein zusätzliches Leerzeichen steht (was einige als zusätzliche Leerzeile betrachten könnten, aber nach der POSIX-Definition von Text kein gültiger Text ist), würden diese 0 ergeben.
POSIXly:
Dies bedeutet jedoch, dass die Datei vollständig gelesen wird (
tail -r
/tac
würde die Datei bei durchsuchbaren Dateien vom Ende rückwärts lesen). Das gibt1
auf die Ausgabe vonprintf 'x\n '
.quelle
Da Sie tatsächlich nach einer
grep
Lösung fragen, füge ich diese hinzu, die nur auf GNUgrep
basiert (okay, auch mit Shell-Syntax undecho
...):Was mache ich hier?
$(grep -c ".*" "$1")
zählt alle Zeilen in der Datei, dann subtrahieren wir die Datei ohne die nachfolgenden leeren Zeilen.Und wie bekommt man die?
$(grep -B42 . "$1"
würde alle nicht leeren Zeilen und 42 Zeilen vor ihnen erfassen, so dass alles bis zur letzten nicht leeren Zeile gedruckt wird, solange nicht mehr als 42 aufeinanderfolgende leere Zeilen vor einer nicht leeren Zeile stehen. Um diese Grenze zu vermeiden, nehme ich$(grep -cv . "$1")
als Parameter für die-B
Option die Gesamtzahl der leeren Zeilen, also immer groß genug. Auf diese Weise habe ich die nachgestellten leeren Zeilen entfernt und kann sie|grep -c ".*"
zum Zählen der Zeilen verwenden.Genial, nicht wahr? (-;
quelle
tac | grep
zum ersten nicht leeren mit-m -A 42
, dann minus eins. Ich bin mir nicht sicher, was effizienter ist, aber Sie könnten auch,wc -l | cut -d' ' -f1
anstatt die leeren Zeilen zu greifen?tac
,wc
undcut
, aber hier habe ich versucht, mich darauf zu beschränkengrep
. Man kann es Perversität nennen, ich nenne es Sport. (-;Eine andere
awk
Lösung. Diese Variante setzt den Zähler zurückk
jedes Mal zurück, wenn eine nicht leere Zeile vorhanden ist. Dann erhöht jede Zeile den Zähler. (Also nach der ersten nicht leeren Zeilek==0
.) Am Ende geben wir die Anzahl der Zeilen aus, die wir gezählt haben.Bereiten Sie die Datendatei vor
Zählen Sie die nachfolgenden Leerzeilen in der Probe
In dieser Definition kann eine Leerzeile Leerzeichen oder andere Leerzeichen enthalten. es ist immer noch leer. Wenn Sie wirklich leere Zeilen anstatt leere Zeilen zählen möchten, ändern Sie
NF
für$0 != ""
.quelle
$0 > ""
? Diese Verwendungen,strcoll()
die weniger effizient wären als$0 != ""
die Verwendungenmemcmp()
in vielen Implementierungen (POSIX erforderte jedoch die Verwendungstrcoll()
).$0 > ""
das anders sein könnte als$0 != ""
. Ich neigeawk
sowieso dazu, als "langsamer" Operator zu behandeln (wenn ich weiß, dass ich einen großen Datensatz als Eingabe habe und die Verarbeitung zeitkritisch ist, werde ich sehen, was ich tun kann, um dieawk
zu verarbeitende Menge zu reduzieren - ichgrep | awk
in solchen Situationen Konstrukte verwendet haben ). Um jedoch einen kurzen Blick auf das, was gehabt zu haben ich nehme an, das ist POSIX Definition ich keinen Hinweis auf entweder sehenstrcoll()
odermemcmp()
. Was vermisse ich?strcoll()
== Die Zeichenfolgen werden anhand der länderspezifischen Sortierfolge verglichen . Vergleiche mit der vorherigen Ausgabe . Ich war derjenige, der es ansprach. Siehe auch austingroupbugs.net/view.php?id=963a <= b && a >= b
nicht unbedingt die gleiche ist wiea == b
. Autsch!awk
oderbash
(für seine[[ a < b ]]
Operatoren) in en_US.UTF-8-Gebietsschemas auf GNU-Systemen, zum Beispiel für①
vs②
(fürbash
, keines von<
,>
gibt=
für diese true zurück). Wahrscheinlich ist es ein Fehler in der Definition dieser Gebietsschemas mehr als in bash / awkFest
awk
+tac
Lösung:Beispiel
input.txt
:Die Aktion:
!NF
- stellt sicher, dass die aktuelle Zeile leer ist (keine Felder hat)NR==++c
- Sicherstellen der fortlaufenden Reihenfolge der Leerzeilen. (NR
- Datensatznummer,++c
- gleichmäßig inkrementierter Hilfszähler)cnt++
- Zähler von LeerzeilenDie Ausgabe:
quelle
IIUC, das folgende Skript
count-blank-at-the-end.sh
würde den Job erledigen:Anwendungsbeispiel:
Getestet habe ich es in
GNU bash
,Android mksh
und inksh
.quelle
Alternative
Python
Lösung:Beispiel input.txt:
Die Aktion:
Die Ausgabe:
https://docs.python.org/3/library/itertools.html?highlight=itertools#itertools.takewhile
quelle