Determine o número de linhas exclusivas com awk ou similar no bash

4

Estou usando o AWK para ler um arquivo de log personalizado que tenho. O formato é algo assim:

[12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.4:8091 HTTP/1.0" 200

Neste momento, tenho o AWK (do bash) configurado para ler todo o log, analisar cada linha e pegar cada linha que contém o "CONNECT" que funciona, no entanto, isso não me ajuda a descobrir clientes únicos.

A maneira de fazer isso seria filtrá-lo de alguma forma para que ele analisasse essa parte de cada linha:     "CONNECT 192.168.2.4:8091 HTTP / 1.0"

Se houvesse uma maneira de pegar todas essas linhas em um arquivo de log, compare-as e contasse apenas linhas semelhantes como uma. Então digamos, por exemplo:

 [12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.6:8091 HTTP/2.0" 200
 [12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.9:8091 HTTP/2.0" 200
 [12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.2:8091 HTTP/2.0" 200
 [12:08:00 +0000] 192.168.2.3 98374 "CONNECT 192.168.2.9:8091 HTTP/2.0" 200

Neste caso, a resposta que eu preciso seria 3, não 4. Porque 2 linhas são iguais, então existem apenas 3 linhas únicas. O que eu preciso é de uma maneira automatizada para conseguir isso com o AWK.

Se alguém puder dar uma mão que seria ótima.

    
por Mark Sander 19.03.2013 / 09:31

3 respostas

3

Você pode deixar o awk contar instâncias exclusivas como esta:

awk -F\" '/CONNECT/ && !seen[$2] { seen[$2]++ } END { print length(seen) }' logfile

Saída:

3

Isso coleta a primeira cadeia entre aspas duplas das linhas que contêm CONNECT na matriz hash seen . Quando o final da entrada é atingido, o número de elementos em seen é impresso.

    
por 19.03.2013 / 13:14
3

sed -re 's/.*"([^"]*)".*//' <logfile> |sort |uniq

Variante do awk: awk -F'"' {print $2} <logfile> |sort |uniq

Adicione -c a uniq para obter uma contagem de cada linha correspondente ou |wc -l para obter uma contagem do número de linhas correspondentes.

    
por 19.03.2013 / 10:09
0

Executando o arquivo de log por meio de ordenação | O uniq deve filtrar as linhas duplicadas, mas eu questionaria porque você tem essas linhas lá. Eles são realmente duplicados?

Se forem entradas de registro legítimas e você quiser apenas uma lista exclusiva de clientes (o segundo campo) para linhas que não sejam duplicatas, uma simples modificação do script do @ Thor deverá fornecer o que você deseja:

awk '
/CONNECT/ {
  if (seen[$0] == 0) {
    clients[$3]++
  }
  seen[$0]++ 
} 
END {
  for (i in clients) {
    print i
  }
}'

Que para a amostra que você deu resultados:

192.168.2.3

Isso não é tão compacto quanto o roteiro de Thor, mas eu geralmente acho que, assim que eu escrevo algo assim, eu quero fazer mais com as linhas, então eu deixei o array visto contagem de linhas únicas) lá.

    
por 19.03.2013 / 23:19

Tags