Quel est l'opposé de la tête? Je veux tout sauf les N premières lignes d'un fichier

142

Étant donné un fichier texte de longueur inconnue, comment puis-je lire, par exemple, toutes les lignes du fichier sauf les 2 premières? Je sais que je tailvais me donner les N dernières lignes, mais je ne sais pas ce que N est à l'avance.

Donc pour un fichier

AAAA
BBBB
CCCC
DDDD
EEEE

Je voudrais

CCCC
DDDD
EEEE

Et pour un dossier

AAAA
BBBB
CCCC

J'aurais juste

CCCC
Nicholas MT Elliott
la source

Réponses:

211

tail --help donne ce qui suit:

  -n, --lines=K            output the last K lines, instead of the last 10;
                           or use -n +K to output lines starting with the Kth

Donc, pour filtrer les premières 2lignes, -n +3devrait vous donner la sortie que vous recherchez (à partir de la 3e).

Joe Enos
la source
2
Curieusement, ma page de manuel ne répertorie pas l'option, mais cela fonctionne très bien - merci!
Nicholas MT Elliott
@ Nicholas: Bizarre, j'ai pensé que ce serait une documentation standard quel que soit le système d'exploitation. J'ai tiré cela de Cygwin dans Windows, donc je ne sais pas à quoi cela ressemble dans diverses distributions Linux. Heureux que cela ait fonctionné.
Joe Enos
@NicholasMTElliott man7 le répertorie comme la page de manuel de Joe Enos, il s'agit donc probablement d'un problème de version de page de manuel
Uli Köhler
@SteveJorgensen: Je ne comprends pas à quoi votre commentaire fait référence; personne ne semble suggérer d'utiliser headpour cela?
ruakh
22

En supposant que votre version de tail le supporte, vous pouvez spécifier le début de la queue après X lignes. Dans votre cas, vous feriez 2 + 1.

tail -n +3

[mdemaria@oblivion ~]$ tail -n +3 stack_overflow.txt
CCCC
DDDD
EEEE
Mike DeMaria
la source
12

Une solution simple utilisant awk:

awk 'NR > 2 { print }' file.name
janm
la source
L'un de nous est confus. Les questions disent: "toutes sauf les 2 premières lignes du fichier". Comment cette commande ne répond-elle pas à l'exigence?
janm
6
{ print }est l'action par défaut et peut être omise.
tripleee
8

Essayez sed 1,2d. Remplacez-en 2 au besoin.

lhf
la source
a fonctionné comme prévu .. car le nombre de lignes après les 2 premières lignes est inconnu.
kumarprd
6

tail -n +linecount filenamecommencera la sortie à la ligne linecountde filename, donc tail -n +3 filename devriez faire ce que vous voulez.

Jim Lewis
la source
Cela ne fonctionnerait pas dans ma coquille mais le tail -n +17 filenameferait. J'utilise bash / ubuntu LTS
isomorphismes
2
@iso: Merci pour le heads-up - les anciennes versions de tailacceptaient la syntaxe que j'ai utilisée dans ma réponse originale, mais maintenant il faut utiliser l' -noption explicite . J'ai mis à jour ma réponse en conséquence.
Jim Lewis
0

Utilisez ceci, en supposant que le premier échantillon s'appelle sample1.dat alors tail --lines=3 sample1.datqui imprimerait toutes les lignes de la 3ème ligne à la dernière ligne.

Pour le deuxième échantillon, supposons à nouveau qu'il s'appelle sample2.dat ce serait ce qui afficherait tail --lines=-1 sample2.datla dernière ligne ...

t0mm13b
la source
@Jim: quelle est la différence avec le vôtre et le mien? .... même chose ....: o Je faisais référence aux deux exemples d'entrées de fichier de données selon sa question et montrant comment réaliser ce qu'il cherchait ... .
t0mm13b
Ok ... alors pourquoi a-t-il demandé le deuxième échantillon et montré le résultat qu'il voulait, c'est ce que j'ai utilisé 'tail --lines = -1' ...... bien sûr, vous pouvez omettre complètement le nom de fichier et c'est toujours peut agir comme un tuyau ... hmm
t0mm13b
@tommie: Oups, oubliez ce que j'ai dit à propos des tuyaux ... J'ai dû penser à un autre utilitaire. Mais mon point était qu'une seule commande,, tail +3 anyfiledonne les résultats souhaités pour le cas général, tout en tail --lines=Nnécessitant de connaître N à l'avance pour donner le résultat souhaité.
Jim Lewis
@tommie: Mais c'est tail... ça ne devrait pas être "de bas en haut"? (Ba-dum TISH! Merci, je serai là toute la semaine ...)
Jim Lewis
0

Je ne sais vraiment pas comment le faire à partir de la queue ou de la tête, mais avec l'aide de wc -l(nombre de lignes) et de l'expression bash, vous pouvez y parvenir.

tail -$(( $( wc -l $FILE | grep -Eo '[0-9]+' ) - 2 )) $FILE

J'espère que cela t'aides.

NawaMan
la source
1
Cela nécessite un passage complet sur le fichier avant d'exécuter tail. Si le fichier est supérieur à la taille de la mémoire, ce sera très inefficace. Il ne gère pas les fichiers de moins de deux lignes. Il ne gère pas le fichier changeant de taille entre le wc et la queue.
janm
2
@janm: Vous allez bien. D'autres réponses sont tout simplement meilleures. Je me sens gêné. :-p
NawaMan
-1

utiliser awk pour obtenir toutes les lignes sauf les 2 dernières

awk 'FNR==NR{n=FNR}FNR<=n-3{print}' file file

awk pour obtenir tout sauf les 2 premières lignes

awk 'NR>2' file

OU vous pouvez utiliser plus

more +2 file

ou juste bash

#!/bin/bash

i=0
while read -r line
do
  [[ $i > 1 ]] && echo "$line"
  ((i++))
done <"file"
ghostdog74
la source
Maintenant, cela ne répond pas à l'exigence. La question dit "toutes sauf les 2 premières lignes du fichier" et donne deux exemples, chacun avec un seul fichier, où les deux premières lignes sont sautées et le reste du fichier est envoyé à stdout. Ce n'est pas ce que fait cette commande.
janm
oui j'ai mal lu la question. pensait qu'il demandait tout sauf les 2 dernières lignes.
ghostdog74