Qual è l'opposto della testa? Voglio tutto tranne le prime N righe di un file


142

Dato un file di testo di lunghezza sconosciuta, come posso leggere, ad esempio tutte tranne le prime 2 righe del file? So tailche mi daranno le ultime N righe, ma non so che N sia in anticipo.

Quindi per un file

AAAA
BBBB
CCCC
DDDD
EEEE

Voglio

CCCC
DDDD
EEEE

E per un file

AAAA
BBBB
CCCC

Vorrei solo

CCCC

Risposte:


211

tail --help dà quanto segue:

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

Quindi, per filtrare le prime 2righe, -n +3dovresti fornirti l'output che stai cercando (a partire dalla terza).


2
Stranamente, la mia pagina man non elenca l'opzione, ma funziona benissimo - grazie!
Nicholas MT Elliott,

@Nicholas: Strano, ho pensato che sarebbe stata una documentazione standard indipendentemente dal sistema operativo. L'ho estratto da Cygwin all'interno di Windows, quindi non so come si presenta in varie distro Linux. Sono contento che abbia funzionato.
Joe Enos,

@NicholasMTElliott man7 liste IT come pagina man Joe Enos', quindi è probabile che sia un problema di versione manpage
Uli Köhler

@SteveJorgensen: non capisco a cosa si riferisca il tuo commento; nessuno sembra suggerire di usare headper questo?
Ruakh,

22

Supponendo che la tua versione di coda la supporti, puoi specificare di iniziare la coda dopo le linee X. Nel tuo caso, faresti 2 + 1.

tail -n +3

[mdemaria@oblivion ~]$ tail -n +3 stack_overflow.txt
CCCC
DDDD
EEEE

12

Una soluzione semplice che utilizza awk:

awk 'NR > 2 { print }' file.name

Uno di noi è confuso. La domanda dice: "tutto tranne le prime 2 righe del file". In che modo tale comando non soddisfa il requisito?
Jan

6
{ print }è l'azione predefinita e può essere omessa.
tripleee,

8

Prova sed 1,2d. Sostituire 2 se necessario.


ha funzionato come previsto .. poiché il numero di righe dopo le prime 2 righe è sconosciuto.
kumarprd,

6

tail -n +linecount filenameinizierà l'output alla riga linecountdi filename, quindi tail -n +3 filename dovrebbe fare quello che vuoi.


Questo non funzionerebbe nella mia shell ma tail -n +17 filenameavrebbe funzionato. Uso bash / ubuntu LTS
isomorphismes il

2
@iso: Grazie per l'heads-up - le versioni precedenti di hanno tailaccettato la sintassi che ho usato nella mia risposta originale, ma ora è necessario utilizzare l' -nopzione esplicita . Ho aggiornato la mia risposta di conseguenza.
Jim Lewis,

0

Utilizzare questo, supponendo che il primo campione sia chiamato sample1.dat, tail --lines=3 sample1.datche quindi stamperebbe tutte le righe dalla terza riga all'ultima riga.

Per il secondo esempio, supponiamo di nuovo che sia chiamato sample2.dat, tail --lines=-1 sample2.datche stamperebbe l'ultima riga ...


@Jim: qual è la differenza tra la tua e la mia? .... stessa cosa ....: o mi riferivo ai due input di file di dati di esempio secondo la sua domanda e mostravo come ottenere ciò che stava cercando ... .
t0mm13b

Ok ... allora perché ha chiesto il secondo campione e ha mostrato il risultato che voleva, che è quello che ho usato 'tail --lines = -1' ...... ovviamente puoi omettere completamente il nome del file ed è ancora può agire come un tubo ... hmm
t0mm13b

@ Tommy: Oops, dimentica quello che ho detto sulle pipe ... Devo aver pensato a qualche altra utilità. Ma il mio punto era che un singolo comando, tail +3 anyfilefornisce i risultati desiderati per il caso generale, mentre tail --lines=Nrichiede di conoscere N in anticipo per ottenere il risultato desiderato.
Jim Lewis,

@tommie: Ma questo è tail... non dovrebbe essere "bottom up"? (Ba-dum TISH! Grazie, sarò qui tutta la settimana ...)
Jim Lewis,

0

Non so davvero come farlo solo dalla coda o dalla testa, ma con l'aiuto di wc -l(conteggio delle righe) e dell'espressione bash, puoi ottenerlo.

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

Spero che questo ti aiuti.


1
Ciò richiede un passaggio completo sul file prima di eseguire tail. Se il file è maggiore della dimensione della memoria, questo sarà molto inefficiente. Non gestisce i file meno di due righe. Non gestisce il file cambiando dimensione tra il wc e la coda.
Jan

2
@janm: stai bene. Altre risposte sono semplicemente migliori. Mi sento in imbarazzo. :-p
NawaMan,

-1

usando awk per ottenere tutto tranne le ultime 2 righe

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

awk per ottenere tutto tranne le prime 2 righe

awk 'NR>2' file

O puoi usarne di più

more +2 file

o semplicemente bash

#!/bin/bash

i=0
while read -r line
do
  [[ $i > 1 ]] && echo "$line"
  ((i++))
done <"file"

Ora questo non soddisfa i requisiti. La domanda dice "tutte tranne le prime 2 righe del file" e fornisce due esempi, ciascuno con un singolo file, in cui le prime due righe vengono ignorate e il resto del file viene inviato a stdout. Questo non è ciò che fa questo comando.
Jan

Sì, ho letto male la domanda. pensò che gli fosse chiesto tutto tranne le ultime 2 righe.
ghostdog74,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.