Co jest przeciwieństwem głowy? Chcę mieć wszystkie oprócz pierwszych N wierszy pliku

142

Biorąc pod uwagę plik tekstowy o nieznanej długości, jak mogę odczytać na przykład wszystkie oprócz pierwszych 2 wierszy pliku? Wiem, tailże poda mi ostatnie N wierszy, ale nie wiem, jakie N wyprzedza czas.

Więc jeśli chodzi o plik

AAAA
BBBB
CCCC
DDDD
EEEE

chcę

CCCC
DDDD
EEEE

I do pliku

AAAA
BBBB
CCCC

Dostałbym tylko

CCCC
Nicholas MT Elliott
źródło

Odpowiedzi:

211

tail --help podaje co następuje:

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

Tak więc, aby odfiltrować pierwsze 2wiersze, -n +3powinno dać wynik, którego szukasz (zacznij od trzeciego).

Joe Enos
źródło
2
Co dziwne, moja strona podręcznika nie zawiera listy opcji, ale działa dobrze - dzięki!
Nicholas MT Elliott
@Nicholas: Dziwne, pomyślałem, że będzie to standardowa dokumentacja niezależnie od systemu operacyjnego. Wyciągnąłem to z Cygwin w systemie Windows, więc nie wiem, jak to wygląda w różnych dystrybucjach Linuksa. Cieszę się, że zadziałało.
Joe Enos
@NicholasMTElliott man7 wymienia to jak stronę podręcznika Joe Enosa, więc prawdopodobnie będzie to problem z wersją strony podręcznika
Uli Köhler
@SteveJorgensen: Nie rozumiem, do czego odnosi się twój komentarz; nikt nie wydaje się sugerować użycia headdo tego?
ruakh
22

Zakładając, że twoja wersja taila to obsługuje, możesz określić początek ogona po X liniach. W twoim przypadku zrobiłbyś 2 + 1.

tail -n +3

[mdemaria@oblivion ~]$ tail -n +3 stack_overflow.txt
CCCC
DDDD
EEEE
Mike DeMaria
źródło
12

Proste rozwiązanie wykorzystujące awk:

awk 'NR > 2 { print }' file.name
janm
źródło
Jeden z nas jest zdezorientowany. Pytanie brzmi: „wszystkie oprócz pierwszych dwóch wierszy pliku”. Jak to polecenie nie spełnia wymagań?
janm
6
{ print }jest akcją domyślną i można ją pominąć.
tripleee
8

Spróbuj sed 1,2d. W razie potrzeby wymień 2.

lhf
źródło
zadziałał zgodnie z oczekiwaniami .. ponieważ liczba wierszy po pierwszych 2 wierszach jest nieznana.
kumarprd
6

tail -n +linecount filenamerozpocznie produkcję na linii linecountz filename, więc tail -n +3 filename powinni robić, co chcesz.

Jim Lewis
źródło
To nie zadziała w mojej powłoce, ale zadziała tail -n +17 filename. Używam bash / ubuntu LTS
izomorfizmy
2
@iso: Dzięki za ostrzeżenie - starsze wersje tailprzyjęły składnię, której użyłem w mojej pierwotnej odpowiedzi, ale teraz trzeba użyć wyraźnej -nopcji. Odpowiednio zaktualizowałem moją odpowiedź.
Jim Lewis
0

Użyj tego, zakładając, że pierwsza próbka nazywa się sample1.dat, tail --lines=3 sample1.datco spowoduje wypisanie wszystkich wierszy od trzeciego do ostatniego wiersza.

Jeśli chodzi o drugą próbkę, ponownie przypuśćmy, że nazywa się sample2.dat, tail --lines=-1 sample2.datco spowodowałoby wydrukowanie ostatniej linii ...

t0mm13b
źródło
@Jim: jaka jest różnica między twoim a moim? .... to samo ....: o Odniosłem się do dwóch przykładowych danych wejściowych do pliku danych zgodnie z jego pytaniem i pokazałem, jak osiągnąć to, czego szukał ... .
t0mm13b
Ok ... więc dlaczego poprosił o drugą próbkę i pokazał wynik, którego chciał, czyli to, co użyłem 'tail --lines = -1' ...... oczywiście możesz całkowicie pominąć nazwę pliku i nadal może pełnić rolę rury ... hmm
t0mm13b
@tommie: Ups, zapomnij, co powiedziałem o rurach ... Musiałem myśleć o jakimś innym narzędziu. Chodziło mi jednak o to, że jedno polecenie tail +3 anyfiledaje pożądane wyniki dla przypadku ogólnego, a jednocześnie tail --lines=Nwymaga znajomości N z wyprzedzeniem, aby uzyskać pożądany rezultat.
Jim Lewis
@tommie: Ale to jest tail... czy to nie powinno być „do dołu”? (Ba-dum TISH! Dziękuję, będę tu cały tydzień ...)
Jim Lewis
0

Naprawdę nie wiem, jak to zrobić, używając tylko ogona lub głowy, ale za pomocą wc -l(liczby linii) i ekspresji basha możesz to osiągnąć.

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

Mam nadzieję że to pomoże.

NawaMan
źródło
1
Wymaga to pełnego przejścia przez plik przed uruchomieniem tail. Jeśli plik jest większy niż rozmiar pamięci, będzie to bardzo nieefektywne. Nie obsługuje plików mniejszych niż dwie linie. Nie obsługuje zmiany rozmiaru pliku między wc i ogonem.
janm
2
@janm: Wszystko w porządku. Inne odpowiedzi są po prostu lepsze. Czuję się zawstydzony. :-p
NawaMan
-1

używając awk do pobrania wszystkich oprócz ostatnich 2 linii

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

awk, aby uzyskać wszystkie oprócz pierwszych 2 wierszy

awk 'NR>2' file

LUB możesz użyć więcej

more +2 file

lub po prostu bash

#!/bin/bash

i=0
while read -r line
do
  [[ $i > 1 ]] && echo "$line"
  ((i++))
done <"file"
ghostdog74
źródło
Teraz to nie spełnia wymagań. Pytanie mówi „wszystkie oprócz pierwszych 2 wierszy pliku” i podaje dwa przykłady, każdy z jednym plikiem, w którym pierwsze dwa wiersze są pomijane, a pozostała część pliku jest wysyłana na standardowe wyjście. To nie jest to, co robi to polecenie.
janm
tak, źle odczytałem pytanie. pomyślał, że jest pytany o wszystkie oprócz ostatnich 2 wierszy.
ghostdog74