Méthode Bash pour afficher le début et la fin du fichier


8

Sur les clusters basés sur la file d'attente, la file d'attente des travaux en attente est affichée à partir d'une commande, par exemple showqueue.

La commande renvoie, en colonnes, une liste de données raisonnables comme les noms, etc., mais les colonnes / données n'ont pas vraiment d'importance pour la question.

J'aime utiliser l'utilitaire watchcomme watch showqueueparfois (avec un alias de alias watch="watch "pour forcer l'expansion d'alias de ma commande à regarder). Il y a des données précieuses (travaux en cours), dans les premières lignes, puis des travaux en attente, etc., et quelques résumés précieux à la fin.

Cependant, parfois la sortie de showqueue disparaît de l'écran (Incroyable, je sais)! Idéalement, j'aimerais avoir un moyen de voir le début et la fin du fichier en même temps.

Le meilleur que j'ai jusqu'à présent est:, showqueue > file; head -n 20 file > file2; echo "..." >> file2 ; tail -n 20 file >> file2; cat file2et en utilisant watchun alias de cela.

Quelqu'un sait-il quelque chose d'un peu plus flexible ou d'un seul utilitaire? Ma solution devient un peu plus désagréable avec des boucles bash pour rendre le "..." break multilined, ce n'est pas du tout adaptatif au redimensionnement de la fenêtre du terminal, et je suis sûr qu'il y a plus que j'ai manqué.

Aucune suggestion?


Fermé en double, mais la question ne partage que des similitudes (la mienne concerne plus une commande, j'ai appris, pas des fichiers), et les réponses ici ne se sont pas présentées là-bas, mais si vous insistez
MadisonCooper

2
C'est suffisant. J'ai rouvert. Notez que la réponse que vous avez acceptée ne fonctionnera que pour les grandes sorties comme indiqué dans ma réponse à la commande pour afficher les premières et dernières lignes d'un fichier (essayez seq 30 | (head && tail)par exemple).
Stéphane Chazelas

2
Je voulais cette réponse . Ce Q&A a deux réponses à moi parce qu'un autre Q&A a été fusionné avec lui (voir l' historique des questions )
Stéphane Chazelas

Réponses:


14

Cherchez-vous à faire quelque chose comme ce qui suit? Affiche la sortie de la tête et de la queue.

$ showqueue | (head && tail)

6
Certaines implémentations de headpeuvent lire plus de 10 lignes et ne laisser rien tailà lire. L'utilitaire n'est pas censé faire cela et je pense que les outils GNU se comportent bien à cet égard. Utilisez-le également head; echo '...'; tailpour obtenir les points.
Kusalananda

Oui, combiné avec le commentaire de @ Kusalananda, c'est beaucoup plus succinct que ma solution. Je vais marquer comme correct pour l'instant! Merci.
MadisonCooper

4
@Kusalananda, non, sur mon système, la tête GNU (coreutils 8.26) lit des blocs de 8192 octets. Il essaie de chercher en arrière, mais évidemment pas en cas de pipe. Quoi qu'il en soit, y a-t-il vraiment une obligation headde ne pas trop lire? (même sur Mac, il semble lire par blocs)
ilkkachu

2
@ilkkachu ouais, même en l'état, la partie de la queue est parfois vide même sur une sortie suffisamment longue (je sais depuis que j'utilise head -n 35, et c'est plein), mais heureusement c'est juste une commodité à regarder et je peux attendre 3 secondes pour un rafraîchissement si nécessaire.
MadisonCooper

3
@Kusalananda, POSIX permet aux implémentations de le faire lorsque l'entrée n'est pas recherchée et la plupart des implémentations le font. Ne pas le faire signifierait lire un octet à la fois, ce qui serait très inefficace (ou remettre les données sur le canal où elles sont prises en charge, ce qui provoquerait toutes sortes de problèmes différents). La seule headimplémentation que je connaisse qui lit un octet à la fois pour éviter de lire après le 10e saut de ligne est la fonction intégrée de headksh93.
Stéphane Chazelas

2

En utilisant la même approche que vous, en utilisant un fichier temporaire, mais en le faisant légèrement plus court:

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

Cela ne souffrirait pas des mêmes problèmes que discuté dans une autre réponse , mais serait peut - être montrer les mêmes lignes deux fois si la sortie était inférieure à 40 lignes.


+1 Je pensais à la même solution avec la légère variation de l'utilisation teepour laisser la sortie entrer directement headet en utilisant uniquement la sortie enregistrée pour tail.
Joe

2

solution awk pour un nombre arbitraire de lignes affichées depuis la tête et la queue (changez n=3pour définir le montant):

$ 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

Comme il est écrit, les parties tête et queue ne se chevaucheront pas , même si l'entrée est plus courte que les 2*nlignes.

Dans certaines implémentations awk, l'utilisation for (x in a) print a[x];dans la ENDpartie fonctionne également. Mais en général, il n'est pas garanti de retourner les entrées du tableau dans le bon ordre, et ce n'est pas le cas par exemple dans mawk.


Si mest le nombre de lignes dans le fichier, et m < 2n, cela imprimera 2n - mles lignes vides. Regardez aussi ici ;-). for (x in a)va itérer dans l'ordre uniquement dans GNU awk ; si vous pensez que cela fonctionne mawkaussi, testez avec> 10 valeurs.
mosvy

@mosvy, oh, oups, j'ai oublié de revérifier qu'après avoir réalisé que ce x in an'était pas bien. Fixé maintenant, merci. Il y a aussi une autre réponse awk dans la question à laquelle Stéphane est lié. J'aime bien le truc modulo!
ilkkachu

0

Vous pouvez utiliser un simple script awk. Ajout d'un tampon circulaire n = 3 pour les 3 dernières lignes

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 )

Après la mise à jour, ce n'est plus simple,


1
Cela ne montrerait que la première et la dernière ligne. Pour afficher plus que cela, vous devez passer NR==1à NR <= 10(ou quelque chose), puis collecter des lignes dans un tampon (circulaire?) Que vous sortirez plus tard dans le ENDbloc.
Kusalananda

oui permettez-moi de mettre à jour
Abdurrahim

Cela imprimera deux lignes deux fois lorsque le nombre de lignes sera inférieur à 2 * n.
mosvy

:) ok en ajoutant que maintenant je suis curieux de savoir ce que vous trouverez ensuite: D
Abdurrahim
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.