Qual é o oposto da cabeça? Quero todas, exceto as primeiras N linhas de um arquivo

142

Dado um arquivo de texto de tamanho desconhecido, como posso ler, por exemplo, exceto as 2 primeiras linhas do arquivo? Eu sei que tailvai me dar as últimas N linhas, mas não sei o que N está adiantado.

Então, para um arquivo

AAAA
BBBB
CCCC
DDDD
EEEE

eu quero

CCCC
DDDD
EEEE

E para um arquivo

AAAA
BBBB
CCCC

Eu ficaria

CCCC
Nicholas MT Elliott
fonte

Respostas:

211

tail --help fornece o seguinte:

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

Portanto, para filtrar as primeiras 2linhas, -n +3deve fornecer a saída que você está procurando (comece da 3ª).

Joe Enos
fonte
2
Estranhamente, minha página de manual não lista a opção, mas funciona muito bem - obrigado!
Nicholas MT Elliott
@ Nicolas: Estranho, achei que seria uma documentação padrão, independentemente do sistema operacional. Peguei isso do Cygwin dentro do Windows, então não sei como ele é em várias distribuições Linux. Ainda bem que funcionou.
18710 Joe Enos
@NicholasMTElliott man7 listas de TI como manpage Joe Enos', por isso é provável que seja um problema de versão manpage
Uli Köhler
@ SteveJorgensen: Não entendo a que seu comentário se refere; ninguém parece sugerir usar headpara isso?
ruakh 5/09/19
22

Supondo que sua versão do tail o suporte, você pode especificar o início do tail após X linhas. No seu caso, você faria 2 + 1.

tail -n +3

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

Uma solução simples usando o awk:

awk 'NR > 2 { print }' file.name
janm
fonte
Um de nós está confuso. As perguntas dizem: "todas, exceto as 2 primeiras linhas do arquivo". Como esse comando não atende ao requisito?
JANM
6
{ print }é a ação padrão e pode ser omitida.
Tripleee
8

Tente sed 1,2d. Substitua 2 conforme necessário.

lhf
fonte
funcionou como esperado .. como número de linhas após as 2 primeiras linhas são desconhecidas.
precisa saber é o seguinte
6

tail -n +linecount filenameiniciará a saída na linha linecountde filename, portanto tail -n +3 filename , faça o que quiser.

Jim Lewis
fonte
Isso não funcionaria no meu shell, mas funcionaria tail -n +17 filename. Eu uso o LTS do bash / ubuntu
isomorphismes
2
@iso: Obrigado pela atenção - as versões mais antigas da tailaceitaram a sintaxe que usei na minha resposta original, mas agora é preciso usar a -nopção explícita . Atualizei minha resposta de acordo.
Jim Lewis
0

Use isso, supondo que a primeira amostra seja chamada sample1.dat e, em seguida tail --lines=3 sample1.dat, imprima todas as linhas da terceira linha até a última linha.

Para a segunda amostra, suponha novamente que é chamado sample2.dat, o tail --lines=-1 sample2.datque imprimiria a última linha ...

t0mm13b
fonte
@ Jim: qual é a diferença entre o seu e o meu? ... a mesma coisa ....: o Eu estava me referindo às duas entradas de arquivo de dados de amostra de acordo com sua pergunta e mostrando como alcançar o que ele estava procurando ... .
t0mm13b
Ok ... então por que ele pediu a segunda amostra e mostrou o resultado que ele queria, que é o que eu usei 'tail --lines = -1' ...... é claro que você pode omitir o nome do arquivo completamente e ainda assim pode atuar como um cano ... hmm
t0mm13b 18/08/10
@ tommie: Opa, esqueça o que eu disse sobre tubos ... Eu devo estar pensando em alguma outra utilidade. Mas meu argumento era que um único comando, tail +3 anyfilefornece os resultados desejados para o caso geral, enquanto tail --lines=Nrequer o conhecimento prévio de N para fornecer o resultado desejado.
Jim Lewis
@ Tommie: Mas isso é tail... não deveria ser "parte de baixo"? (! Ba-dum Tish Obrigado, eu serei aqui toda a semana ...)
Jim Lewis
0

Realmente não sei como fazê-lo apenas com cauda ou cabeça, mas com a ajuda de wc -l(contagem de linhas) e expressão do bash, você pode conseguir isso.

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

Espero que isto ajude.

NawaMan
fonte
1
Isso requer uma passagem completa sobre o arquivo antes de executar o tail. Se o arquivo for maior que o tamanho da memória, isso será muito ineficiente. Ele não processa arquivos com menos de duas linhas. Ele não lida com o tamanho do arquivo alterado entre o wc e a cauda.
JANM
2
@janm: Você está bem. Outras respostas são apenas melhores. Eu me sinto envergonhado. :-p
NawaMan
-1

usando o awk para obter todos, exceto as duas últimas linhas

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

awk para obter todas, exceto as 2 primeiras linhas

awk 'NR>2' file

OU você pode usar mais

more +2 file

ou apenas bater

#!/bin/bash

i=0
while read -r line
do
  [[ $i > 1 ]] && echo "$line"
  ((i++))
done <"file"
ghostdog74
fonte
Agora isso não atende aos requisitos. A pergunta diz "todas, exceto as 2 primeiras linhas do arquivo" e fornece dois exemplos, cada um com um único arquivo, onde as duas primeiras linhas são ignoradas e o restante do arquivo é enviado ao stdout. Não é isso que esse comando faz.
JANM
Sim, eu interpretei mal a pergunta. pensei que ele é pedir para todos, mas últimas 2 linhas.
ghostdog74