Negatywne argumenty na głowie / ogonie

14

Warianty tego pytania z pewnością zadawano kilka razy w różnych miejscach, ale staram się usunąć ostatnie Mwiersze z pliku bez powodzenia.

Drugi najbardziej głosowało odpowiedź na to pytanie zaleca wykonanie następujących czynności, aby pozbyć się ostatniej linii w pliku:

head -n -1 foo.txt > temp.txt

Jednak gdy próbuję tego w OSX i Zsh, otrzymuję:

head: illegal line count -- -1

Dlaczego? Jak mogę usunąć M ostatnie wiersze i przez pierwsze N linie danego pliku?

Amelio Vazquez-Reina
źródło
1
Zobacz, że głowa i ogon POSIX nie mają odpowiednika
Stéphane Chazelas,
1
Jaka jest wydajność head --version? Z jakiego systemu korzystasz?
jofel
@ jofel head --versionfaktycznie zwraca błąd.
Amelio Vazquez-Reina,

Odpowiedzi:

20

Możesz usunąć pierwsze 12 linii za pomocą:

tail -n +13

(Oznacza to wydruk z 13. linii).

Niektóre implementacje headpodobnej headobsługi GNU :

head -n -12

ale to nie jest standard.

tail -r file | tail -n +12 | tail -r

działałby na tych systemach, które mają tail -r(patrz także GNU tac), ale nie są optymalne.

Gdzie njest 1:

sed '$d' file

Możesz także:

sed '$d' file | sed '$d'

aby usunąć 2 linie, ale to nie jest optymalne.

Możesz to zrobić:

sed -ne :1  -e 'N;1,12b1' -e 'P;D'

Ale uwaga: niektóre implementacje nie będą działać z dużymi wartościami nsed .

Z awk:

awk -v n=12 'NR>n{print line[NR%n]};{line[NR%n]=$0}'

Aby usunąć mlinie od początku i nod końca:

awk -v m=6 -v n=12 'NR<=m{next};NR>n+m{print line[NR%n]};{line[NR%n]=$0}'
Stéphane Chazelas
źródło
sed 'x;1d;$d'może być również użyty do uzyskania dwóch ostatnich linii. I kilka Nsekund później 1dmożna by użyć, aby uzyskać trochę więcej, chociaż w tym momencie nie oferuje żadnej przewagi nad N;P;Dpętlą, którą już polecasz.
mikeserv
Dziękuję - ostatnie polecenie jest niezwykle pomocne. A latem małe zastrzeżenie: to nie działa, gdy malbo n0. W przeciwnym razie byłoby idealnie.
Amelio Vazquez-Reina
2

Możesz użyć następującego sposobu, aby usunąć pierwsze N ​​linii i ostatnie M. linii.

Z N=5, M=7a plik test.txt:

sed -n -e "6,$(($(wc -l < test.txt) - 7))p" test.txt

Polecenie drukuje wszystkie linie od N + 1 do LastLine-M.

Inną opcją jest użycie Pythona:

python -c 'import sys;print "".join(sys.stdin.readlines()[5:-7]),' < test.txt
Jofel
źródło
1

Możesz usunąć ostatnie M(tutaj M = 100) wiersze z pliku za pomocą:

head -$(($(wc -l < foo.txt) - 100)) foo.txt > temp.txt
robić
źródło