maneira do awk para adicionar números em campos de linha

0

data.now:

blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=92 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=92 Auto_save__of__retention__data__completed=1 Warning___Return=68 PASSIVE__SERVICE__CHECK_=53 ,1026--1313,1
blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=14 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=93 Auto_save__of__retention__data__completed=1 Warning___Return=68 PASSIVE__SERVICE__CHECK_=53 ,1026--1313,1
blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=93 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=92 Auto_save__of__retention__data__completed=1 Warning___Return=8 PASSIVE__SERVICE__CHECK_=53 ,1026--1313,1
blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=73 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=99 Auto_save__of__retention__data__completed=1 Warning___Return=68 PASSIVE__SERVICE__CHECK_=53 ,1026--1313,1
blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=93 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=75 Auto_save__of__retention__data__completed=1 Warning___Return=38 PASSIVE__SERVICE__CHECK_=53 ,1026--1313,1
blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,on__host=21 SERVICE__ALERT_=51 Warning___The__results__of__service=16 Warning___on__host=12 Auto_save__of__retention__data__completed=1 Warning___Return=28 PASSIVE__SERVICE__CHECK_=23 ,1026--1313,1[/CODE]

Os campos em cada linha acima são separados por "vírgula". O que me interessa é o campo 9.

O campo 9 tem vários valores.

O que eu quero fazer é duas partes:

  1. Ser capaz de somar todos os valores de um padrão específico em todas as linhas no arquivo de dados. Por exemplo, se eu quiser saber o valor total "on__host" em todas as linhas no arquivo de dados.

  2. Ser capaz de somar todos os valores de todos os padrões em cada linha, em todas as linhas no log.

Havia um dado antigo com o qual eu estava trabalhando, o qual tinha apenas um único valor no nono campo. isso era fácil de manusear. Os dados ficaram assim:

data.prev

blah1,dah,blaha,sweet,games.log,5297484456,nagios-toin,529748456,53,1026--1313,1

E tudo que eu precisava fazer para somar os valores no 9º campo de todas as linhas era:

awk -F, 'BEGIN{sum=0} {sum+=$9} END {print sum}' data.prev

O tipo de script que resolveria esse problema para mim seria assim:

#!/bin/sh
Pattern=$1
if [ "${Pattern}" = "allpatterns" ] ; then
   awk should add up all the values in the 9th field of data in data.now
else
   if the user did not specify "allpatterns", then, awk should take the pattern name specified by the user and use that to decide which pattern to add up in the 9th field of all the lines.
    awk -F"," '$9 ~ /'${Pattern}'/ '{do awk magic}'  -- this is just an idea.
fi

espera-se que este script seja executado em todos os sistemas unix. O shell que eu vou usar é / bin / sh ou / bin / bash.

Para a primeira parte do meu pedido, se todos os valores de todos os padrões em todas as linhas no arquivo de dados forem somados, a saída deve ser apenas a soma resultante dos números ... ou 504 (apenas um valor arbitrário). número eu escolhi).

Para a segunda parte da minha solicitação, se os valores de um padrão específico forem somados, a saída deverá ser apenas a soma resultante dos valores desse padrão específico ... ou seja, "on__host = 400".

    
por swenson 15.10.2017 / 07:33

2 respostas

0

Para a primeira parte, acho que algo assim funcionaria:

cat data.now | awk -F, '{print $9}' | sed 's/=/ /g' | awk '
    { 
        for (i = 1; i <= NF; i += 2) {
            a[$i]+=$(i+1); 
        }
    } 
    END {
        for (i in a) print i, "=", a[i]
    }'

Este código produz a seguinte saída:

PASSIVE__SERVICE__CHECK_ = 288
Warning___Return = 278
Auto_save__of__retention__data__completed = 6
SERVICE__ALERT_ = 306
Warning___The__results__of__service = 96
on__host = 386
Warning___on__host = 463

O único problema em potencial aqui é que o pedido não é o mesmo que o do arquivo original. Se o pedido é importante para você, você pode usar:

cat data.now | awk -F, '{print $9}' | sed 's/=/ /g' | awk '
    { 
        for (i = 1; i <= NF; i += 2) {
            a[$i]+=$(i+1); 
            b[i]=$i;
        }
    } 
    END {
        for (i in b) print b[i], "=", a[b[i]]
    }'

mas não é tão fácil de ler.

Para sua segunda pergunta, acho que isso funciona para calcular a soma, embora possa não ser a maneira mais curta ou mais eficiente de fazê-lo.

cat data.now | awk -F, '{print $9}' | 
    sed "s/.*\<${Pattern}=\([0-9]\+\).*//g" | 
    awk '{s += $1} END {print s}'
    
por 15.10.2017 / 13:23
0

Você pode split arquivar $9 no espaço, depois iterar sobre o resultado para selecionar o padrão e split o elemento encontrado em = para extrair o valor:

awk -F, -v pat='^on__host=' '{
  n = split($9,a," "); 
  for(i=1;i<=n;i++) {
    if(a[i] ~ pat) {
      split(a[i],b,"="); 
      sum+=b[2]
    } 
  }
} 
END{print sum}
' data.now 
    
por 15.10.2017 / 14:16