Bash-Methode zum Anzeigen von Anfang und Ende der Datei

8

In warteschlangenbasierten Clustern wird die Warteschlange ausstehender Jobs beispielsweise über einen Befehl angezeigt showqueue.

Der Befehl gibt in Spalten eine Liste vernünftiger Daten wie Namen usw. zurück, aber die Spalten / Daten sind für die Frage nicht wirklich wichtig.

Ich benutze das Dienstprogramm manchmal watchgerne watch showqueue(mit dem Alias alias watch="watch ", um die Alias-Erweiterung meines Befehls zum Beobachten zu erzwingen). In den ersten Zeilen befinden sich wertvolle Daten (Ausführen von Jobs), dann ausstehende Jobs usw. und am Ende einige wertvolle Zusammenfassungen.

Manchmal geht die Ausgabe von Showqueue jedoch vom Bildschirm (Unglaublich, ich weiß)! Im Idealfall möchte ich auf irgendeine Weise den Anfang und das Ende der Datei gleichzeitig sehen können.

Das Beste, was ich bisher habe, ist: showqueue > file; head -n 20 file > file2; echo "..." >> file2 ; tail -n 20 file >> file2; cat file2und unter Verwendung watcheines Alias ​​davon.

Kennt jemand etwas, das etwas flexibler oder einfacher ist? Meine Lösung wird mit Bash-Schleifen etwas unangenehmer, damit die "..." - Unterbrechung mehrzeilig wird. Sie ist überhaupt nicht anpassbar, um die Größe des Terminalfensters zu ändern, und ich bin sicher, dass ich noch mehr verpasst habe.

Irgendwelche Vorschläge?

MadisonCooper
quelle
Als Duplikat geschlossen, aber die Frage hat nur Ähnlichkeiten (meine Frage handelt eher von einem Befehl, wie ich gelernt habe, und nicht von Dateien), und die Antworten hier wurden dort nicht
angezeigt
2
Meinetwegen. Ich habe wieder geöffnet. Beachten Sie, dass die Antwort, die Sie akzeptiert haben, nur für große Ausgaben funktioniert, wie bei meiner Antwort unter Befehl angegeben, um die ersten und letzten Zeilen einer Datei anzuzeigen (versuchen Sie es seq 30 | (head && tail)beispielsweise).
Stéphane Chazelas
2
Ich meinte diese Antwort . Die Q & A hat zwei Antworten von mir , weil ein anderen Q & A mit ihm verschmolzen wurde (siehe Frage Geschichte )
Stéphane Chazelas

Antworten:

14

Möchten Sie so etwas wie das Folgende tun? Zeigt die Ausgabe von Kopf und Schwanz an.

$ showqueue | (head && tail)
Timothy Pulliam
quelle
6
Einige Implementierungen von headlesen möglicherweise mehr als 10 Zeilen und lassen nichts tailzum Lesen übrig . Das Dienstprogramm wird nicht angenommen , das zu tun , und ich glaube , dass die GNU - Tools sind in dieser Hinsicht verhalten. Verwenden Sie head; echo '...'; tail, um die Punkte auch dort zu bekommen.
Kusalananda
Ja, zusammen mit @ Kusalanandas Kommentar ist es viel prägnanter als meine Lösung. Ich werde vorerst als richtig markieren! Vielen Dank.
MadisonCooper
4
@Kusalananda, nein, auf meinem System liest der GNU-Kopf (coreutils 8.26) Blöcke mit 8192 Bytes. Es versucht zwar , zurück zu suchen, kann es aber im Falle einer Pfeife offensichtlich nicht. Gibt es wirklich eine Anforderung head, nicht zu viel zu lesen? (gleich auf Mac, scheint es durch die Blöcke zu lesen)
ilkkachu
2
@ilkkachu Ja, auch wenn es so aussieht, ist der Heckteil gelegentlich leer, selbst bei ausreichend langer Ausgabe (ich weiß, da ich head -n 35 verwende, und das ist voll), aber zum Glück ist es nur eine Annehmlichkeit zu sehen und ich kann 3 warten Sekunden für eine Aktualisierung bei Bedarf.
MadisonCooper
3
@Kusalananda, POSIX ermöglicht Implementierungen, dies zu tun, wenn die Eingabe nicht durchsuchbar ist und die meisten Implementierungen dies tun. Wenn Sie dies nicht tun, lesen Sie jeweils ein Byte, was sehr ineffizient wäre (oder setzen Sie die Daten wieder auf die Pipe, wo sie unterstützt werden, was zu unterschiedlichsten Problemen führen würde). Die einzige headmir bekannte Implementierung, die jeweils ein Byte liest, um zu vermeiden, dass über die 10. Zeilenumbruch hinaus gelesen wird, ist die headintegrierte Version von ksh93 .
Stéphane Chazelas
2

Verwenden Sie den gleichen Ansatz wie Sie, verwenden Sie eine temporäre Datei, aber etwas kürzer:

showqueue >/tmp/q.out; head -n 20 /tmp/q.out; echo '...'; tail -n 20 /tmp/q.out

Dies würde nicht von den gleichen Problemen leiden , wie diskutiert unter einer anderen Antwort , aber würde möglicherweise die gleichen Zeilen zweimal zeigen , wenn die Ausgabe kürzer als 40 Zeilen sind.

Kusalananda
quelle
+1 Ich dachte an die gleiche Lösung mit der geringfügigen Variation der Verwendung tee, um die Ausgabe direkt zu verwenden, headund nur der gespeicherten Ausgabe für tail.
Joe
2

awk-Lösung für eine beliebige Anzahl von Linien, die vom Kopf und vom Schwanz angezeigt werden (ändern n=3, um die Menge einzustellen):

$ seq 99999 | awk -v n=3 'NR <= n; NR > n { a[NR] = $0; delete a[NR-n]; } 
     END { print "..."; for (i = NR-n+1; i <= NR; i++) if (i in a) print a[i]; }'
1
2
3
...
99997
99998
99999

Wie geschrieben, überlappen sich die Kopf- und Schwanzteile nicht , selbst wenn die Eingabe kürzer als die 2*nZeilen ist.

In einigen awk-Implementierungen funktioniert auch die Verwendung for (x in a) print a[x];im ENDTeil. Im Allgemeinen wird jedoch nicht garantiert, dass die Array-Einträge in der richtigen Reihenfolge zurückgegeben werden, und dies ist beispielsweise nicht der Fall.

ilkkachu
quelle
Wenn mist die Anzahl der Zeilen in der Datei, und m < 2n, werden 2n - mleere Zeilen gedruckt . Schauen Sie auch hier ;-). for (x in a)wird in der Reihenfolge nur in GNU awk iterieren ; Wenn Sie denken, dass es auch funktioniert mawk, testen Sie mit> 10 Werten.
Mosvy
@ Mosvy, oh, hoppla, ich habe vergessen, das noch einmal zu überprüfen, nachdem mir klar x in awurde , dass es nicht richtig war. Jetzt behoben, danke. Es gibt auch eine andere Antwort in der Frage, mit der Stéphane verbunden ist. Ich mag den Modulo-Trick!
Ilkkachu
0

Sie können ein einfaches awk-Skript verwenden. Der hinzugefügte Kreispuffer dort n = 3 gilt für die letzten 3 Zeilen

awk 'NR<=n {print $0} { A[NR%n]=$0 } END { for (i=1; i<=n; ++i) if (NR+i>2*n)print A[(NR+i)%n] }' n=3 < <( seq 10 )

Nach dem Update ist es allerdings nicht mehr einfach,

Abdurrahim
quelle
1
Dies würde nur die erste und letzte Zeile anzeigen. Um mehr als das anzuzeigen, müssten Sie NR==1zu NR <= 10(oder etwas) wechseln und dann Zeilen in einem (kreisförmigen?) Puffer sammeln, den Sie später im ENDBlock ausgeben .
Kusalananda
Ja, lassen Sie mich aktualisieren
Abdurrahim
Dadurch werden einige Zeilen zweimal gedruckt, wenn die Anzahl der Zeilen weniger als 2 * n beträgt.
Mosvy
:) ok, füge das jetzt auch hinzu. Ich bin gespannt, was du als nächstes finden wirst: D
Abdurrahim