Bash: conta ocorrências de valor na coluna x com base no valor da coluna y

1

Eu tenho uma string como essa.

data = "state:: 4 caller_contact:: sip:[email protected]:5080;transport=udp

state:: 4 caller_contact:: sip:[email protected]:5080;transport=udp

state:: 4 caller_contact:: sip:[email protected]:5080;transport=udp 

state:: 4 caller_contact:: sip:[email protected]:5080;transport=udp

state:: 2 caller_contact:: sip:[email protected]:5080;transport=udp 

state:: 2 caller_contact:: sip:[email protected]:5080;transport=udp 

state:: 1 caller_contact:: sip:[email protected]:5080;transport=udp"

Eu preciso escrever um script bash para contar quantas vezes cada IP, por exemplo, 192.168.26, tem o estado 4 ou o estado 2. (esta cadeia não contém '/ n')

Não é possível analisar essa string e contar valores de acordo com cada IP.

    
por user3310052 12.08.2016 / 19:51

4 respostas

1

Não tenho certeza se isso funcionará para todas as combinações possíveis que você possa ter, mas funciona para a pequena amostra que você forneceu:

sed  "1,\$s/state/\nstate/g" file | grep state > NewFile
for IPADDR in $(cat NewFile | cut -d"@" -f2|cut -d":" -f1|sort -n|uniq);do
  for STATE in 2 4 ;do
    LineCount=$(grep "${IPADDR}" NewFile |grep "state:: ${STATE}"| wc -l)
    echo "For IP address ${IPADDR}, status:: ${STATE} lines count is ${LineCount}"
  done
done | grep -v "is 0"$

você pode adicionar quantos números diferentes quiser no loop for dentro

Basicamente, você está inserindo um novo caractere de linha antes de cada ocorrência da string state , fazendo seu grande bloco de dados, separando em várias linhas.

    
por 12.08.2016 / 20:05
0

Encontre IPs únicos e conte cada um com o estado 4 ou 2

for addr in $(grep -o '@[^:]\+' file | sort -u); do 
    echo -n ${addr#@}:\ 
    grep -c ":: [24].*${addr#@}" file
done

Ou faça uma tarefa com o awk

awk -F '[: @;=]+' '
    $2 ~ /^[24]$/{
        count[$6]++
        }
    END {
        for(i in count)
            print(i, count[i])
        }
    ' file
    
por 12.08.2016 / 22:13
0

Aqui está meu pequeno monstro.

#!/bin/bash 
# monsterr.sh

if [ -z "$1" ] ; then
    printf "%s\n" "Syntax error."
    exit 2
fi

data="$1"

tmp=tmp$$
mkdir $tmp

parse() {
    state=
    ip=
    i=0
    while read l; do
        ((i++))
        if [ $(($i%2)) -eq 0 ]; then
            if [ $(($i%4)) -eq 2 ]; then
                state=$l
            else
                IFS=: read x ip x < <(printf %s $l)
                IFS=@ read x ip < <(printf %s $ip)
                printf "%s\n" $state >> "$tmp/$ip"
            fi
        fi
    done <  <(printf "%s\n" $data)
}


report() {
    cd $tmp
    for f in * ; do
        declare -a count
        printf "IP: %s\n" $f
             while read s ; do
                ((count[$s]++))
            done < $f
        for s in ${!count[@]}; do
            printf "State: %s, count: %s\n" $s ${count[$s]}
        done
        printf '\n'
        unset count
    done
    cd - 2 > /dev/null
}

parse
report

rm -r $tmp

Uso:

$ data="state:: 4 caller_contact:: sip:[email protected]:5080;transport=udp state:: 4 caller_contact:: sip:[email protected]:5080;transport=udp state:: 4 caller_contact:: sip:[email protected]:5080;transport=udp state:: 4 caller_contact:: sip:[email protected]:5080;transport=udp state:: 2 caller_contact:: sip:[email protected]:5080;transport=udp  state:: 2 caller_contact:: sip:[email protected]:5080;transport=udp state:: 1 caller_contact:: sip:[email protected]:5080;transport=udp"
$ ./monsterr.sh "$data"
IP: 192.168.10.01
State: 4, count: 1

IP: 192.168.10.03
State: 4, count: 1

IP: 192.168.10.07
State: 1, count: 1

IP: 192.168.10.11
State: 2, count: 1
State: 4, count: 1

IP: 192.168.10.26
State: 2, count: 1
State: 4, count: 1
    
por 12.08.2016 / 22:34
0

grep das linhas que você deseja manipular, isso é possível com sed . Obtenha 2 substrings de sua linha com sed , classifique e conte:

sed -n '/state:: [24] .*@/ s/.*:: \([24]\)[^@]*@\([^:]*\).*/State  IP /p' file |
 sort | uniq -c | sort -n
    
por 14.08.2016 / 17:34