Argumentos negativos para cabeça / cauda

13

Variantes desta pergunta certamente foram feitas várias vezes em lugares diferentes, mas estou tentando remover as últimas Mlinhas de um arquivo sem sorte.

A resposta segundo mais votado em esta pergunta recomenda fazer o seguinte para se livrar da última linha em um arquivo:

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

No entanto, quando tento isso no OSX e no Zsh, recebo:

head: illegal line count -- -1

Por que é que? Como posso remover as M últimas linhas e as primeiras N linhas de um determinado arquivo?

Amelio Vazquez-Reina
fonte
1
Qual é a saída de head --version? Que sistema voce está usando?
Jofel
@jofel head --versionretorna um erro, na verdade.
Amelio Vazquez-Reina

Respostas:

19

Você pode remover as 12 primeiras linhas com:

tail -n +13

(Isso significa imprimir a partir da 13ª linha.)

Algumas implementações do suporte ao headGNU como head:

head -n -12

mas isso não é padrão.

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

funcionaria nos sistemas que possuem tail -r(veja também GNU tac), mas é sub-ideal.

Onde nfica 1:

sed '$d' file

Você também pode fazer:

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

para remover 2 linhas, mas isso não é o ideal.

Você pode fazer:

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

Mas cuidado, isso não funcionará com grandes valores de n em algumas sedimplementações.

Com awk:

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

Para remover mlinhas do começo e ndo fim:

awk -v m=6 -v n=12 'NR<=m{next};NR>n+m{print line[NR%n]};{line[NR%n]=$0}'
Stéphane Chazelas
fonte
sed 'x;1d;$d'pode ser usado para obter as duas últimas linhas também. E um par de Nsegundos depois 1dpode ser usado para obter um pouco mais do que isso, embora nesse momento não ofereça nenhuma vantagem sobre o N;P;Dloop que você já recomenda.
mikeserv
Obrigado - O último comando é extremamente útil. Uma pequena ressalva de verão: não funciona quando mou né 0. Caso contrário, seria perfeito.
Amelio Vazquez-Reina
2

Você pode usar a seguinte maneira para remover as primeiras N linhas e as últimas M linhas.

Com N=5, M=7e arquivo test.txt:

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

O comando imprime todas as linhas de N + 1 para LastLine-M.

Outra opção é usar python:

python -c 'import sys;print "".join(sys.stdin.readlines()[5:-7]),' < test.txt
jofel
fonte
1

Você pode remover as últimas M(aqui M = 100) linhas de um arquivo com:

head -$(($(wc -l < foo.txt) - 100)) foo.txt > temp.txt
faço
fonte