Contagem do número total de linhas antes / depois de uma correspondência de padrões

8

Estou tendo uma longa lista de endereços IP, que não estão em sequência. Preciso encontrar quantos endereços IP existem antes / depois de um determinado endereço IP. Como posso conseguir isso?

    
por Mandar Shinde 24.07.2014 / 17:10

7 respostas

7

Número de linhas antes e depois de uma correspondência, incluindo a correspondência (ou seja, você precisa subtrair 1 do resultado se quiser excluir a correspondência):

sed -n '0,/pattern/p' file | wc -l
sed -n '/pattern/,$p' file | wc -l

Mas isso não tem nada a ver com endereços IP em particular.

    
por 24.07.2014 / 17:29
4

Talvez o mais fácil seja

sed -n '/pattern/{=; q;}' file

Obrigado @JoshepR por apontar o erro

    
por 24.07.2014 / 17:31
3

Eu fiz isso de duas maneiras, embora eu ache que eu gosto disso:

: $(( afterl=( lastl=$(wc -l <~/file) ) - 2 -
  $(( beforel=( matchl=$(sed -n "/$IP/{=;q;}" <~/file) ) - 1
)) ))
for n in last match afters befores
do  printf '%s line%s :\t%d\n' \
        "${n%s}" "${n##*[!s]}" $((${n%s}l))
done

Isso salva todas as variáveis atuais do shell - e as avalia no loop for depois para a saída. Ele conta o total de linhas no arquivo com wc e obtém o primeiro número de linha correspondente com sed .

Sua saída:

last line :     1000
match line :    200
after lines :   799
before lines :  199

Eu também fiz:

sed -n "/$IP/=;\$=" ~/file |  
tr \n \  | { 
IFS=' ' read ml ll 
printf '%s line%s:\t%d\n' \
    last '' $((ll=${ll##* }))
    match '' $ml \
    after s "$((al=ll-ml-1)) \ 
    before s $((bl=ml-1))
}

sed imprime apenas números de correspondência e de última linha, em seguida, tr traduz o% coexistente de ewlines para e \n lê o primeiro dos resultados de read em sed e todos os outros em $ml . Possíveis casos de múltiplas correspondências são tratados removendo todos, exceto o último resultado, da expansão de $ll ao configurá-lo novamente mais tarde.

Sua saída:

last line :     1000
match line :    200
after lines :   799
before lines :  199

Ambos os métodos foram testados no arquivo gerado da seguinte maneira:

IP='some string for which I seek' 
for count in 1 2 3 4 5 
do  printf '%.199d%s\n' 0 "$IP" 
done | tr 0 \n >~/file 

Por número de linha:

  1. define a string de pesquisa
  2. faz um loop cinco vezes para garantir que haverá várias correspondências
  3. imprime 199 zeros e, em seguida, $ll , em seguida, um "$IP" ewline
  4. saída de tubos para \n - que converte zeros em tr ewlines em seguida em \n
por 24.07.2014 / 21:31
2

Aqui está um pequeno código Perl que faz isso:

perl -ne '
     if(1 .. /192\.168\.1\.1/) { $before++ }
     else                      { $after++  }
     $before--; # The matching line was counted
     END{print "Before: $before, After: $after\n"}' your_file

Isso conta o número total de linhas antes e depois da linha que contém o IP 192.168.1.1 . Substitua pelo seu IP desejado.

Usando nada além de Bash:

before=0
match=0
after=0
while read line;do
    if [ "$line" = 192.168.1.1 ];then
        match=1
    elif [ $match -eq 0 ];then
        before=$(($before+1))
    else
        after=$(($after + 1))
    fi
done < your_file
printf "Before: %d, After: %d\n" "$before" "$after"
    
por 24.07.2014 / 17:28
2

Eu estava tentando os seguintes comandos, que são um pouco complicados, mas dariam resultados precisos:

Depois:

a=$(cat file | wc -l) && b=$(cat -n file | grep <Pattern> | awk '{print $1}') && echo "$a - $b" | bc -l

Antes:

echo "'cat -n file | grep <Pattern> | awk '{print $1}''-1" | bc -l
    
por 24.07.2014 / 17:41
2

Uma solução awk informa o número de linhas antes e depois da última correspondência

awk '/192\.168\.1\.1/{x=NR};{y=NR} END{printf "before-%d, after-%d\n" , x-1, y-x}'  file
    
por 24.07.2014 / 19:20
1

Grep tem um recurso que pode contar o número de vezes que um determinado padrão é encontrado. Se você usar o comando -c , isso será feito. Com o comando -c e -v , isso contará quantas vezes isso não corresponder a um padrão específico

Exemplo:

grep -c -v <pattern> file

Então, se você tentar algo como:

grep -c -v 192.168.x.x file.log que deve funcionar. Espero que isso ajude.

    
por 24.07.2014 / 17:17