Como posso contar o número de linhas em um arquivo após uma correspondência grep?

14

Estou tentando contar o número de linhas após uma linha problemática em um arquivo csv. Estou ciente de que posso usar a grep -a #sintaxe para gerar # número de linhas depois que uma correspondência foi encontrada. Estou interessado apenas no número real de linhas. Percebo que poderia definir o número como MAX_INT, canalizá-lo em um arquivo e fazer mais processamento.

Estou procurando uma linha sucinta para me contar a contagem.

Alguma sugestão?

NathanChristie
fonte

Respostas:

15
{ grep -m1 match; grep -c ''; } <file

Isso funcionará com GNU grepe um lseek()infile capaz. O primeiro greppara em 1 -mpolegada e o segundo -cdesativa todas as linhas restantes na entrada.

Sem GNU grep:

{ sed '/match/q'; grep -c ''; } <file

Obviamente, grepvocê pode usar qualquer uma das outras opções além disso, e parar em uma partida não é de todo necessário.

mikeserv
fonte
Ambos também imprimem a linha, e o segundo imprime até a primeira correspondência e depois 0 para mim?
123
@ User112638726 - é claro que você pode soltar a impressão da primeira partida grep -m1 match >/dev/null. E seu segundo problema é um GNU sed- ele não redefine seu deslocamento de entrada por especificação. Você precisa usar -uw / GNU - o que nem sempre é desejável. Eu poderia ter sido mais claro, mas minha suposição era que um GNU grepe GNU sedviriam em pares. Eu acho que também grep -qm1poderia funcionar para atalho para o /dev/nullredirecionamento - mas o GNU grepfaz coisas estranhas com -qe não consigo me lembrar de como esses dois trabalham juntos.
mikeserv
1
Boa resposta - realmente demonstra o poder dos grupos de comando. Não sei ao certo, mas acho que wc -lé um pouco mais barato que grep -c ''.
Digital Trauma
1
@DigitalTrauma - Sim, eu considerei (em retrospecto) , mas eu já tinha escrito, e quase rimado, então achei que deixaria o bastante em paz. E de qualquer maneira, você disse isso também, então eu vou dormir fácil agora.
mikeserv
9

Aqui está uma maneira.

$ cat foo
aaa
bbb
ccc
ddd
eee
fff
$ awk '/^ddd/{a=FNR}END{print FNR-a}' foo
2
$
Steve
fonte
4
isso não é codegolf, você pode dar detalhes (FNR, END e assim por diante)?
Archemar
3
Certo. O awk usa o FNR para identificar o número do registro de entrada. END é o código executado ao chegar ao final do arquivo. Portanto, quando uma correspondência é encontrada, o número do registro atual é gravado. Ao chegar ao final do arquivo, esse número é subtraído do número total de linhas no arquivo.
steve
1
Também pode usar NR, pois é um arquivo.
123
6

Outra maneira - o uso de dcé um pouco esotérico, mas parece funcionar bem aqui:

sed -n '/problem/=;$=' prob.txt | dc -e '??r-p'

sedprocura prob.txtpor "problema" e a última linha e usa o =comando para gerar o número da linha de ambos.

dc lê esses dois valores na pilha, os reverte, subtrai e imprime a diferença.

Trauma Digital
fonte
5

Inteiramente com sed (embora dois comandos com um cano)

sed '/ddd/,$!d' file | sed -n '$='

Exclui toda a linha antes da linha e, em seguida, o próximo comando conta as linhas no novo arquivo.

123
fonte
3

Isso deve excluir todas as linhas até (e incluindo) a problemática e, em seguida, contar as linhas restantes:

sed '1,/problem/d' data.txt | wc -l
hóspede
fonte
1
(assumindo que "problema" não está na primeira linha)
Stéphane Chazelas