142 votes

unix - tête ET queue du fichier

Disons que vous avez un fichier txt, quelle est la commande pour visualiser simultanément les 10 premières lignes et les 10 dernières lignes du fichier ?

Par exemple, si le fichier compte 200 lignes, affichez les lignes 1 à 10 et 190 à 200 en une seule fois.

0 votes

Que voulez-vous dire par "en une seule fois" ?

0 votes

@cnicutar c.-à-d. ne pas aller tête -10 dossier l'examen des données et ensuite, séparément, je vais faire tail -10 file et l'examen des données

0 votes

@toop Si vous voulez un exemple concret, voir stackoverflow.com/a/44849814/99834

227voto

Aleksandra Zalcman Points 999

Vous pouvez simplement :

(head; tail) < file.txt

Et si vous avez besoin d'utiliser des tuyaux pour une raison quelconque, alors faites comme ça :

cat file.txt | (head; tail)

Note : imprimera les lignes dupliquées si le nombre de lignes dans file.txt est plus petit que les lignes par défaut de head + les lignes par défaut de tail.

59 votes

Strictement parlant, ceci ne vous donne pas la queue du fichier original, mais la queue du flux après head a consommé les 10 premières lignes du fichier. (Comparez cela avec head < file.txt; tail < file.txt sur un fichier de moins de 20 lignes). Juste un point très mineur à garder à l'esprit. (Mais quand même +1.)

18 votes

Sympa. Si vous voulez un espace entre la partie tête et la partie queue : (head;echo;tail) < fichier.txt

3 votes

Je suis curieux de savoir pourquoi et comment cela fonctionne. Je l'ai posé comme une nouvelle question : stackoverflow.com/questions/13718242

19voto

kev Points 41855

ed est le standard text editor

$ echo -e '1+10,$-10d\n%p' | ed -s file.txt

2 votes

Que faire si le fichier a plus ou moins de 200 lignes ? Et que vous ne connaissez pas le nombre de lignes ab initio ?

0 votes

@Paul J'ai changé sed a ed

16voto

RantingNerd Points 31

Pour un flux pur (par exemple la sortie d'une commande), vous pouvez utiliser 'tee' pour bifurquer le flux et envoyer un flux à head et un autre à tail. Cela nécessite l'utilisation de la fonction '>( list )' de bash (+ /dev/fd/N) :

( COMMAND | tee /dev/fd/3 | head ) 3> >( tail )

ou en utilisant /dev/fd/N (ou /dev/stderr) plus des sous-shells avec des redirections compliquées :

( ( seq 1 100 | tee /dev/fd/2 | head 1>&3 ) 2>&1 | tail ) 3>&1
( ( seq 1 100 | tee /dev/stderr | head 1>&3 ) 2>&1 | tail ) 3>&1

(Aucune de ces méthodes ne fonctionnera avec csh ou tcsh).

Pour un contrôle un peu plus précis, vous pouvez utiliser cette commande perl :

COMMAND | perl -e 'my $size = 10; my @buf = (); while (<>) { print if $. <= $size; push(@buf, $_); if ( @buf > $size ) { shift(@buf); } } print "------\n"; print @buf;'

1 votes

+1 pour le support des flux. Vous pourriez réutiliser stderr : COMMAND | { tee >(head >&2) | tail; } |& other_commands

2 votes

En fait, le système s'arrête pour les fichiers dont la taille est supérieure à celle du tampon (8K sur mon système). cat >/dev/null le répare : COMMAND | { tee >(head >&2; cat >/dev/null) | tail; } |& other_commands

0 votes

J'ai adoré la solution, mais après avoir joué un certain temps, j'ai remarqué que dans certains cas, la queue passait avant la tête... il n'y a pas d'ordre garanti entre les deux. head y tail commandes :\ ...

3voto

Samus_ Points 1011

Le problème ici est que les programmes orientés flux ne connaissent pas la longueur du fichier à l'avance (parce qu'il pourrait ne pas y en avoir, s'il s'agit d'un vrai flux).

des outils comme tail met en tampon les n dernières lignes vues et attend la fin du flux, puis imprime.

Si vous voulez faire cela en une seule commande (et que cela fonctionne avec n'importe quel décalage, et ne répète pas les lignes si elles se chevauchent), vous devrez émuler le comportement que j'ai mentionné.

essayez cet awk :

awk -v offset=10 '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) print a[i] }' yourfile

0 votes

Il faut travailler davantage afin d'éviter les problèmes lorsque le décalage est plus grand que le fichier

0 votes

Yay, cela fonctionne avec les sorties pipées, pas seulement avec les fichiers : a.out | awk -v ...

0 votes

En effet :) mais c'est le comportement normal d'awk, la plupart des programmes en ligne de commande fonctionnent sur stdin lorsqu'ils sont invoqués sans arguments.

1voto

Paul Points 3329

Les 10 premières lignes de file.ext, puis ses 10 dernières lignes :

cat file.ext | head -10 && cat file.ext | tail -10

Les 10 dernières lignes du fichier, puis les 10 premières :

cat file.ext | tail -10 && cat file.ext | head -10

Vous pouvez ensuite envoyer la sortie ailleurs également :

(cat file.ext | head -10 && cat file.ext | tail -10 ) | your_program

5 votes

Pourquoi utiliser cat quand on peut simplement appeler head -10 file.txt ?

0 votes

Pouvez-vous rendre le nombre de lignes variable, de sorte que l'appel soit quelque chose comme : head_ tail(foo, m,n) - renvoyant les m premières et les n dernières lignes du texte ?

0 votes

@ricardo cela impliquerait d'écrire un bash script qui prend 3 args et les passe à tail y head ou une fonction en l'aliasant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X