행 필드에 숫자를 추가하는 awk 메소드

행 필드에 숫자를 추가하는 awk 메소드

현재 데이터:

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]

위 각 줄의 필드는 "쉼표"로 구분됩니다. 제가 관심을 갖고 있는 것은 필드 9입니다.

필드 9에는 여러 값이 있습니다.

내가하고 싶은 일은 두 부분입니다.

  1. 모든 값을 더할 수 있습니다.특정 모드데이터 파일의 모든 행에서. 예를 들어, 데이터 파일의 모든 행에 대한 "on__host"의 총 값을 알고 싶은 경우입니다.

  2. 로그의 모든 행에 걸쳐 행당 모든 패턴에 대한 모든 값을 합산하는 기능.

저는 9번째 필드에 하나의 값만 있는 오래된 데이터로 작업하고 있습니다. 이것은 다루기가 쉽습니다. 데이터는 다음과 같습니다:

이전 데이터

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

내가 해야 할 일은 모든 행의 9번째 필드에 있는 값을 더하는 것뿐입니다.

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

이 문제를 해결한 스크립트는 다음과 같습니다.

#!/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

이 스크립트는 모든 UNIX 시스템에서 실행될 것으로 예상됩니다. 제가 사용할 쉘은 /bin/sh 또는 /bin/bash입니다.

요청의 첫 번째 부분에서 데이터 파일의 모든 행에 있는 모든 패턴에 대한 모든 값을 더하면 출력은 숫자의 합이 되어야 합니다. 이는 504(내가 선택한 임의의 숫자)입니다. ).

내 요청의 두 번째 부분에서 특정 패턴에 대한 값을 더하면 출력은 해당 특정 패턴에 대한 값의 합계여야 합니다. 즉, "on__host=400"입니다.

답변1

다음은 수행하기 더 쉬운 작업입니다 ( 보다 수행하기 쉬운 perl작업이 많지는 않습니다 ).awkperl

$ perl -F, -lae '$c{$1} += $2 while $F[8] =~ /(\S+)=(\d+)/g;
                 END {print "$_ => $c{$_}" for sort keys %c}' < file
Auto_save__of__retention__data__completed => 6
PASSIVE__SERVICE__CHECK_ => 288
SERVICE__ALERT_ => 306
Warning___Return => 278
Warning___The__results__of__service => 96
Warning___on__host => 463
on__host => 386

예를 들어 값만 필요한 경우 블록을 END로 변경합니다.{print $c{on__host}}on__host

답변2

첫 번째 부분에서는 다음과 같은 것이 작동할 것이라고 생각했습니다.

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]
    }'

이 코드는 다음과 같은 출력을 생성합니다.

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

여기서 유일한 잠재적인 문제는 순서가 원본 파일의 순서와 다르다는 것입니다. 순서가 중요한 경우 다음을 사용할 수 있습니다.

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]]
    }'

하지만 읽기가 그리 쉽지는 않습니다.

두 번째 질문의 경우 이것이 가장 짧거나 가장 효율적인 방법은 아니지만 합계를 계산할 수 있다고 생각합니다.

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

답변3

공간적으로 split파일링 $9한 다음 결과를 반복하여 패턴을 선택한 다음 split발견된 요소를 찾아 =값을 추출할 수 있습니다.

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 

관련 정보