2016-05-27 7 views
2

私は以下のようなLinuxシステムで日々のファイル出力を持ち、$ 1と平均$ 3と$ 4 $ 5 $ 6 $ 7に基づいて30分ずつデータをグループ化する方法があるのだろうかと思っていましたawk/gawkなどのシェルスクリプトを使って$ 8?bash group timesとaverage + sum columns

04:04:13 04:10:13 2.13 36 27 18 18 0 
04:09:13 04:15:13 2.37 47 38 13 34 0 
04:14:13 04:20:13 2.19 57 37 23 33 1 
04:19:13 04:25:13 2.43 43 35 13 30 0 
04:24:13 04:30:13 2.29 48 40 19 28 1 
04:29:13 04:35:13 2.33 56 42 16 40 0 
04:34:13 04:40:13 2.21 62 47 30 32 0 
04:39:13 04:45:13 2.25 44 41 19 25 0 
04:44:13 04:50:13 2.20 65 50 32 33 0 
04:49:13 04:55:13 2.47 52 38 16 36 0 
04:54:13 05:00:13 2.07 72 54 40 32 0 
04:59:13 05:05:13 2.35 53 41 19 34 0 

はとても基本的にデータのこの時間はこのようなものになるでしょう:

04:04:13-04:29:13 2.29 287 219 102 183 2 
04:34:13-04:59:13 2.25 348 271 156 192 0 

これは私が時間枠の間で検索するのawkを使用して、これまでに得ているものですが、私は簡単にあると思いますグループ分けは、これはあなたが欲しいものを行う必要があり、各30分間隔

awk '$1>=from&&$1<=to' from="04:00:00" to="04:30:00" | awk '{ total += $3; count++ } END { print total/count }'|awk '{printf "%0.2f\n", $1'} 

awk '$1>=from&&$1<=to' from="04:00:00" to="04:30:00" | awk '{ sum+=$4} END {print sum}' 
+0

だから、あなたがこれまでに試してみましたでしょうか? –

+0

awkを使用してハードコードされた時間範囲で値を個別に取得することができますが、これは私が得た限りです。今まで私の主なスレッドを更新しました – user1999357

+0

例えば、次のようにして、時間から分を抽出することができます。 'time = $ 1; min = substr(time、4,2); '、時間と秒でidemを行い、比較テストを書く。 –

答えて

0

をawkingずに終らせる方法:

{ 
    split($1, times, ":"); 
    i = (2 * times[1]); 
    if (times[2] >= 30) i++; 
    if (!start[i] || $1 < start[i]) start[i] = $1; 
    if (!end[i] || $1 > end[i]) end[i] = $1; 
    count[i]++; 
    for (col = 3; col <= 8; col++) { 
     data[i, col] += $col; 
    } 
} 

END { 
    for (i = 1; i <= 48; i++) { 
     if (start[i]) { 
      data[i, 3] = data[i, 3]/count[i]; 
      printf("%s-%s %.2f", start[i], end[i], data[i, 3]); 
      for (col = 4; col <= 8; col++) { 
       printf(" " data[i, col]); 
      } 
      print ""; 
     } 
    } 
} 

ご覧のとおり、私は48時間30分間隔で1日を分割し、最初の列の時間に応じてこれらのビンの1つにデータを配置します。入力が使い尽くされた後、私は空ではないすべてのビンを印刷します。

0

個人的には、私はこれをPythonまたはPerlで行います。 awkでは、配列は順序付けされていません(まあ、gawkではassortiを使って配列をソートすることができます)。ここで

は概要である:

  1. 読む入力
  2. 秒にタイムスタンプを変換する所望の時間枠のバケット内のデータ要素の順序付き(またはソート可能)連想配列に追加(または、合計を実行し続ける)。
  3. データが読み込まれたら、必要に応じて処理してください。ここで

ことのPythonのバージョンです:

あなたの例のデータにそれを実行する
#!/usr/bin/python 

from collections import OrderedDict 
import fileinput 
times=[] 
interval=30*60 
od=OrderedDict() 

for line in fileinput.input(): 
    li=line.split() 
    secs=sum(x*y for x,y in zip([3600,60,1], map(int, li[0].split(":")))) 
    times.append([secs, [li[0], float(li[2])]+map(int, li[3:])]) 

current=times[0][0] 
for t, li in times: 
    if t-current<interval: 
     od.setdefault(current, []).append(li) 
    else: 
     current=t 
     od.setdefault(current, []).append(li) 

for s, LoL in od.items(): 
    avg=sum(e[1] for e in LoL)/len(LoL) 
    sums=[sum(e[i] for e in LoL) for i in range(2,7)] 
    print "{}-{} {:.3} {}".format(LoL[0][0], LoL[-1][0], avg, ' '.join(map(str, sums))) 

$ ./ts.py ts.txt 
04:04:13-04:29:13 2.29 287 219 102 183 2 
04:34:13-04:59:13 2.26 348 271 156 192 0  

利点は、あなたが簡単に間隔を変更することができますであり、同様の技術を使用することができます日よりも長いタイムスタンプ。


あなたが本当にawkをしたい場合は、あなたが行うことができます:

awk 'BEGIN{ interval=30*60 } 
    function fmt(){ 
      line=sprintf("%s-%s %.2f %i %i %i %i %i", ls, $1, sums[3]/count, 
          sums[4], sums[5], sums[6], sums[7], sums[8]) 
    } 
    { 
     split($1,a,":") 
     secs=a[1]*3600+a[2]*60+a[3] 
     if (NR==1) { 
      low=secs 
      ls=$1 
      count=0 
      for (i=3; i<=8; i++) 
       sums[i]=0 
     }      
     for (i=3; i<=8; i++){ 
      sums[i]+=$i 
     } 
     count++   
     if (secs-low<interval) { 
      fmt() 
      }  
     else { 
      print line 
      low=secs 
      ls=$1 
      count=1 
      for (i=3; i<=8; i++) 
       sums[i]=$i       
      }     
    } 
    END{ 
     fmt() 
     print line 
    }' file 
04:04:13-04:29:13 2.29 287 219 102 183 2 
04:34:13-04:59:13 2.26 348 271 156 192 0