Berechnungen mit der Bash

Du suchst ein Programm für einen bestimmten Zweck?
Antworten
root2root
Beiträge: 168
Registriert: 22.10.2007 13:06:29

Berechnungen mit der Bash

Beitrag von root2root » 12.09.2010 07:39:18

Hallo Team,

2 Logdateien (Text) mit dem Format liegen mir vor. Logdatei A mit 43 Einträgen von Tag 1

user_a datum account klicks
user_d datum account klicks
user_b datum account klicks
user_c datum account klicks
...

Logdatei B mit 55 Einträgen von Tag 2

user_c datum account klicks
user_d datum account klicks
user_a datum account klicks
user_b datum account klicks
...

Die numerischen Werte "Klicks" möchte ich so auswerten, daß gerechnet wird :
Klicks von Tag 2 minus Klicks von Tag 1, Ergebnis in neuer Datei mit der größeren useranzahl,
also 55 user, dh. 12 user ohne ergebnis.

Ergebnisdatei mit 55 Einträgen

user_a diff_klicks
user_b diff_klicks
user_c diff_klicks
user_d
user_e
...

im Logdateinamen A und B ist das Tagesdatum enthalten. Da ich sicherstellen will daß keine neg. klicks ausgerechnet werden, muß der Tag 1 von Tag 2 abgezogen werden ( in Tag 2 wurden die klicks aufkummuliert ).

Probiert habe ich folgendes:
mit awk '{print $1 $4}' Tag1.log komme ich schon mal an die user und Klicks

Natülich stehen die user "durcheinander", d.h zum user_a aus Tag1.log muß der user_a aus Tag2.log gefunden werden.

Habt ihr eine Shellscript / Bash -lösung parat ?
Wäre super.

System: DEB Lenny 5.04

gruß root2root

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: Berechnungen mit der Bash

Beitrag von rendegast » 12.09.2010 08:55:31

Code: Alles auswählen

#!/bin/sh

analyze() {
    USERS=$(awk '{print $1}' "$FILE" | sort | uniq)
    for i in $USERS ; do
        egrep "^$i" "$FILE" | awk '{print $1,"x","x",SUM+=$4}' | tail -n1
    done
}

FILE=LogA
analyze | awk '{print $1,"x","x",-$4}'> TempC

FILE=LogB
analyze >> TempC

FILE=TempC
analyze | awk '{print $1,$4}' > Out
(Was sich wohl auch komplett in awk lösen läßt,
ich hänge dann aber erstmal an einer Formulierung

Code: Alles auswählen

awk '$1=="$i" ...'
um grep zu ersetzen.
Und statt des 'tail' hat awk bestimmt auch eine Möglichkeit, nur die Gesamtsumme auszugeben.)
Die "x", damit ich die Funktion dreimal anwenden kann.

Schneller und resourcenschonender wird das Einlesen der Dateien in Arrays ('read'),
und das Anwenden von Aktionen auf die Array-Elemente sein.
Aber meine Version ist auch nur ein dummer shell-Hack. ;)





Sowas zum Beispiel:

Code: Alles auswählen

(
exec 9<$0 <LogA
while read a b c d; do
    echo $a \-$d
done

exec 9<$0 <LogB
while read a b c d; do
    echo $a $d
done
) | sort
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

123456
Beiträge: 6126
Registriert: 08.03.2003 14:07:24

Re: Berechnungen mit der Bash

Beitrag von 123456 » 12.09.2010 13:16:07

wenns nicht unbedingt die bash sein muss eignet sich perl für sowas ganz gut. der Perl Code ist zwar nicht kürzer, liest sich aber IMO etwas einfacher.

Code: Alles auswählen

#! /usr/bin/perl
use strict;
use warnings;

my $path = "/SOME_PATH/";
my %hash1; my %hash2;
my ($key, $date, $val);
    
open (FILE1, "<$path" . "datei1.log");
open (FILE2, "<$path" . "datei2.log");
open (FILE3, ">>$path" . "diff.log");

while (<FILE1>) {
    chomp;
    ($key, $date, $val) = split / /;
    $hash1{$key} = $val;
}
while (<FILE2>) {
    chomp;
    ($key, $date, $val) = split / /;
    $hash2{$key} = $val;
}
foreach $key (keys %hash2) {
    if ($hash1{$key} and $hash2{$key}) {
        print FILE3 ($key, " " , $hash2{$key} - $hash1{$key}, "\n");   
    }
    else {
        print FILE3 ($key, " " , $hash2{$key}, "\n");     
    }
}    
close FILE1; close FILE2; close FILE3;

Antworten