J'ai un fichier avec plusieurs lignes et chaque ligne a un horodatage au début, comme
[Thread-3] (21/09/12 06:17:38:672) logged message from code.....
Donc, je vérifie fréquemment 2 choses dans ce fichier journal.
- Les premières lignes, qui ont les conditions globales et l'heure de début sont également indiquées.
- Dernières lignes, qui ont le statut de sortie avec quelques autres informations.
Existe-t-il une seule commande rapide et pratique qui pourrait me permettre d'afficher uniquement les premières et dernières lignes d'un fichier?
head and tail
fonctionnent pas pour vous?N
sed(1)
expert, mais il existe des moyens de ranger des trucs pour une utilisation ultérieure avec. Peut-être que cela vaut la peine de regarder là-dedans. OTOH, je préparerais probablement un script Perl (ou autre) pour le faire s'il est utilisé fréquemment, car je suis plus familier avec cela.Réponses:
Vous pouvez utiliser
sed
ouawk
pour le faire avec une seule commande. Cependant, vous perdrez de la vitesse, de la causesed
etawk
devrez de toute façon parcourir tout le fichier. Du point de vue de la vitesse, il est préférable de créer une fonction ou à chaque fois de combinertail
+head
. Cela a l'inconvénient de ne pas fonctionner si l'entrée est un canal, mais vous pouvez utiliser la substitution de processus, au cas où votre shell la prend en charge (regardez l'exemple ci-dessous).et lancez-le comme
pour procéder à la substitution de processus (bash, zsh, ksh comme les shells uniquement):
ps. vous pouvez même ajouter un
grep
pour vérifier si vos "conditions globales" existent.la source
-n 10
est la valeur par défaut, non?-n 10
n'est pas nécessaire ici.@rush a raison d'utiliser plus efficacement head + tail pour les gros fichiers, mais pour les petits fichiers (<20 lignes), certaines lignes peuvent être sorties deux fois.
serait tout aussi efficace, mais n'aurait pas le problème ci-dessus.
la source
{head; tail;} < file
fonctionne en zsh mais échoue en sh.{ head; tail;} < file
fonctionne toujours. Désolé pour le bruit.head
, pas avec le shell. POSIX nécessitehead
de laisser le curseur dans le fichier juste après ces 10 lignes pour les fichiers normaux. Un problème pourrait survenir pour leshead
implémentations non-POSIX (les très anciennes versions de GNU head étaient autrefois non conformes dans ce cas, mais nous parlons de décennies) ou si le fichier n'est pas recherchable (comme un tube ou socket nommé, mais une autre solution aurait le même problème).sudo sh -c '{ head; tail;} < /path/to/file'
La
{ head; tail; }
solution ne fonctionnerait pas sur les canaux (ou sockets ou tout autre fichier non recherchable) carhead
pourrait consommer trop de données lors de la lecture par blocs et ne peut pas rechercher sur un canal laissant potentiellement le curseur à l'intérieur du fichier au-delà de ce quitail
est voulu pour sélectionner.Ainsi, vous pouvez utiliser un outil qui lit un caractère à la fois comme celui du shell
read
(ici en utilisant une fonction qui prend le nombre de lignes de tête et de queue comme arguments).ou implémenter
tail
dans awk par exemple comme:Avec
sed
:(mais sachez que certaines
sed
implémentations ont une faible limitation sur la taille de leur espace de motif, donc échoueraient pour de grandes valeurs du nombre de lignes de queue).la source
En utilisant la
bash
substitution de processus, vous pouvez effectuer les opérations suivantes:Notez que les lignes ne sont pas garanties d'être en ordre, bien que pour les fichiers plus longs qu'environ 8 Ko, elles le seront très probablement. Cette coupure de 8 Ko est la taille typique du tampon de lecture et est liée au fait que
| {head; tail;}
cela ne fonctionne pas pour les petits fichiers.Il
cat >/dev/null
est nécessaire de maintenir lehead
pipeline en vie. Sinontee
, vous quitterez tôt, et même si vous obtiendrez une sortie detail
, ce sera quelque part au milieu de l'entrée, plutôt qu'à la fin.Enfin, pourquoi au
>/dev/null
lieu de, disons, passertail
à un autre|
? Dans le cas suivant:head
stdout est injecté dans le tuyautail
plutôt que dans la console, ce qui n'est pas du tout ce que nous voulons.la source
tail
doit travailler plus longtemps, mais je m'attends (et le vois) à un échec environ la moitié du temps pour les entrées courtes.tee >(head) >(tail)
pour les mêmes raisons (>(...)
qui est d'ailleurs une fonctionnalité ksh désormais prise en charge par zsh et bash) utilise également des tuyaux. Vous pouvez le faire,... | (trap '' PIPE; tee >(head) >(tail) > /dev/null)
mais vous verrez toujours des messages d'erreur de tuyaux casséstee
.tail
est celui qui est tué par SIGPIPE, nontee
, et n'écrittail
pas dans un pipe. Donc ça doit venir d'unkill()
, non? Et cela ne se produit que lorsque j'utilise la|
syntaxe.strace
dit que çatee
n'appelle paskill()
... alors peutbash
- être ?seq 100000 | tee >(head -n1) >(tail -n1) > /dev/null
Utilisation
ed
(qui lira cependant le fichier entier dans la RAM):la source
ed -s file <<< $'11,$-10d\n,p\nq\n'
Première solution de Stéphane dans une fonction pour que vous puissiez utiliser des arguments (fonctionne dans n'importe quel shell Bourne-like ou POSIX):
Vous pouvez maintenant le faire:
Cela suppose bien sûr que vous ne regardez qu'un seul fichier et que la solution de Stéphane ne fonctionne (de manière fiable) que sur des fichiers standard (recherchables).
la source
Avec l' option
-u
(--unbuffered
) de GNUsed
, vous pouvez utilisersed -u 2q
comme alternative non tamponnée àhead -n2
:(head -n2;tail -n2)
échoue lorsque les dernières lignes font partie du bloc de l'entrée consommé parhead
:la source
Je suis tombé sur quelque chose comme ça aujourd'hui où je n'avais besoin que de la dernière ligne et de quelques lignes de l'avant d'un flux et j'ai trouvé ce qui suit.
Je lis ceci comme: initialiser l'espace d'attente avec le contenu de la première ligne, ajouter les lignes 2-3 dans l'espace d'attente, à EOF ajouter la dernière ligne à l'espace d'attente, échanger l'espace d'attente et de motif et imprimer le motif espace.
Peut-être quelqu'un avec plus
sed
-FU que moi peut comprendre comment généraliser cette option pour imprimer les dernières quelques lignes du flux indiqués dans cette question , mais je n'ai pas besoin et ne pouvait pas trouver un moyen facile de faire des mathématiques en fonction de l'$
adresse danssed
ou peut-être en gérant l'espace d'attente de sorte que seules les dernières lignes soient dedans quand ilEOF
est atteint.la source
Vous pouvez essayer Perl, si vous l'avez installé:
Cela fonctionnera pour la plupart des fichiers, mais lit tout le fichier en mémoire avant de le traiter. Si vous n'êtes pas familier avec les tranches Perl, "0" entre crochets signifie "prenez la première ligne" et "-3 ...- 1" signifie "prenez les trois dernières lignes". Vous pouvez les adapter tous les deux à vos besoins. Si vous avez besoin de traiter des fichiers vraiment volumineux (ce qui est «gros» peut dépendre de votre RAM et peut-être changer de taille), vous pouvez opter pour:
il peut être un peu plus lent, car il fait une tranche à chaque itération, mais il est indépendant de la taille du fichier.
Les deux commandes devraient fonctionner à la fois dans les canaux et avec les fichiers normaux.
la source