Classificar e contar o número de ocorrências de linhas

145

Eu tenho o Apachearquivo de log, access.logcomo contar o número de ocorrências de linha nesse arquivo? por exemplo, o resultado de cut -f 7 -d ' ' | cut -d '?' -f 1 | tr '[:upper:]' '[:lower:]'é

a.php
b.php
a.php
c.php
d.php
b.php
a.php

o resultado que eu quero é:

3 a.php
2 b.php
1 d.php # order doesn't matter
1 c.php 
Kokizzu
fonte
25
| sort | uniq -c
Costas
3
| LC_ALL=C sort | LC_ALL=C uniq -c
Stéphane Chazelas
ah eu nunca sei que uniqpoderia fazer isso ..
Kokizzu
Você tem um exemplo da linha no log, pois acho que tudo isso poderia ser feito com o awk sem todos os pipes.
está tudo bem, o arquivo de log de 8,1 GB é processado em cerca de 2 minutos e está pronto por enquanto, não precisa mais disso: 3
Kokizzu

Respostas:

196
| sort | uniq -c

Como indicado nos comentários.

A inserção da saída sortorganiza a saída em ordem alfabética / numérica.

Este é um requisito, porque uniqcorresponde apenas a linhas repetidas, ou seja,

a
b
a

Se você usar uniqesse arquivo de texto, ele retornará o seguinte:

a
b
a

Isso ocorre porque os dois as são separados pelo b- eles não são linhas consecutivas. No entanto, se você primeiro classificar os dados em ordem alfabética, como

a
a
b

Em seguida uniq, removerá as linhas repetidas. A -copção de uniqconta o número de duplicatas e fornece saída no formato:

2 a
1 b

Referências:

visudo
fonte
11
Bem-vindo ao Unix e Linux :) Não hesite em adicionar mais detalhes a sua resposta e explicar por que e como isso funciona;)
John WH Smith
11
printf '%s\n' ①.php ②.php | sort | uniq -cdá-me2 ①.php
Stéphane Chazelas
@ StéphaneChazelas Isso porque os printf imprimephp\nphp
4
@ Jidder, não, é porque ①.phpclassifica o mesmo que ②.phpna minha localidade, porque nenhuma ordem de classificação é definida para aqueles e caracteres na minha localidade. Se você quiser únicos valores para quaisquer valores de byte (lembre-se caminhos de arquivo não são necessariamente texto), então você precisa para corrigir o local para C: | LC_ALL=C sort | LC_ALL=C uniq -c.
Stéphane Chazelas
2
Para que o arquivo de contagem resultante seja classificado, considere adicionar o "sort -nr" como as respostas @ eduard-florinescu abaixo.
Lluís Suñol
104
[your command] | sort | uniq -c | sort -nr

A resposta aceita está quase completa. Você pode adicionar um extra sort -nrno final para classificar os resultados com as linhas que ocorrem com mais frequência primeiro

opções uniq :

-c, --count
       prefix lines by the number of occurrences

opções de classificação :

-n, --numeric-sort
       compare according to string numerical value
-r, --reverse
       reverse the result of comparisons

No caso específico em que as linhas que você está classificando são números, você precisa usar em sort -grvez de sort -nr, ver o comentário

Eduard Florinescu
fonte
3
Muito obrigado por me informar sobre a -nopção.
Sigur
2
Grande resposta, aqui está o que eu uso para obter um wordcount fora do arquivo com frases: tr ' ' '\n' < $FILE | sort | uniq -c | sort -nr > wordcount.txt. O primeiro comando substitui espaços por novas linhas, permitindo que o restante do comando funcione conforme o esperado.
Bar
2
Usando as opções acima, obtenho "1" antes de "23344". O uso sort -grresolve isso. -g: compare de acordo com o valor numérico geral (em vez de -n: compare de acordo com o valor numérico da string).
Peter Jaric 14/02
@PeterJaric Ótima captura e muito útil para se conhecer, -grmas acho que a saída de uniq -cserá como tal que sort -nrfuncionará conforme o
esperado
3
Na verdade, quando os dados são números, -grfunciona melhor. Tente estes dois exemplos, diferindo apenas nos sinalizadores g e n: echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -nre echo "1 11 1 2" | tr ' ' '\n' | sort | uniq -c | sort -gr. O primeiro classifica incorretamente, mas não o segundo.
Peter Jaric 15/02
9

Você pode usar uma matriz associativa em awk e depois -optionally- tipo :

cat access.log  | awk ' { tot[$0]++ } END { for (i in tot) print tot[i],i } ' | sort

resultado:

1 c.php
1 d.php
2 b.php
3 a.php
Laurence R. Ugalde
fonte
Como você contaria o número de ocorrências enquanto o canal está enviando dados?
User123456