Durchschnitt von Logfileeinträgen berechnen

D

doonot

Mitglied
Und wieder hallo zusammen :)

ich habe ein logfile mit einer zahl pro zeile ( die einträge erfolgen all 2 minuten, und werden immer überschrieben)

ich möchte jeweils den durchschnitt aller zahlen ausrechnen. für das müsste ich alle zusammenzählen und geteilt an wc -l machen, dass ich einen durchschnittswert bekomme.

wie kann ich alle zusammenrechnen, wenn ich nicht weiss, wie viele einträge vorhanden sind (da diese immer varieren?)

vielen dank
 
na wenn du immer nur einen eintrag in der logfile hast kannst du nicht wissen was vor 10 Minuten war.

Oder sehe ich da was falsch?
 
ne ne, du verstehst mich falsch, mein logfile sieht etwa so aus:

Code:
383214
829872
12446
2098759
209871
578
432
384
528
3204
477
666
341
492
520
295
484
372
77777
731
442
630
272
494
151
268
336
363
1291
693
380
476
293
236
459
560
332

nun möchte ich den durchschnitt (aber ich weiss nicht wieviele zeilen da sind, da das file all 2 minuten überschrieben wird, und ggf. neue zeilen dazu kommen)
 
lies mit grep -c oder cat die zeilenanzahl aus und lass ne addition durch ne schleife jagen mit anschließender division durch die zeilenanzahl

EDIT:
Code:
grep -c . logfile

folgender code gibt dir zumbeispiel die Zeilenanzahl der /var/log/messages in die variable $MSGANZ aus
Code:
MSGANZ=$(grep -c . /var/log/messages)
echo $MSGANZ
 
Zuletzt bearbeitet:
also die Zeilenanzahl habe ich ja schon mit wc -l filename

ich habe gehröt das man mit sort alles adieren kann?

habs mal so versucht, geht aber nicht :(

Code:
 ADD_LOG="awk ' $1 ' testlogfile  | sort "

anschliessend:

Code:
AV_WERT='expr "$ADD_LOG" / $(wc -l testlogfile)'
 
also die Zeilenanzahl habe ich ja schon mit wc -l filename

ich habe gehröt das man mit sort alles adieren kann?

habs mal so versucht, geht aber nicht :(

Code:
 ADD_LOG="awk ' $1 ' testlogfile  | sort "

anschliessend:

Code:
AV_WERT='expr "$ADD_LOG" / $(wc -l testlogfile)'

1.:
Code:
wc -l
gibt dir keine Zahl aus sondern eine Zahl + den Dateinamen (damit kann man nicht rechnen)
2.:
Code:
ADD_LOG=$(awk ' $1 ' testlogfile  | sort )
das gibt dir alle Werte getrennt mit nem Leerzeichen zurück...
3.:
Code:
AV_WERT='expr "$ADD_LOG" / $(wc -l testlogfile)'
kann nicht funktionieren, da du sagst "String mit allen Werten durch Leerzeichen getrennt dividieren durch Zeilen mit Dateinamen."

also mache es wie folgt:
Code:
DIVISOR=$(grep -c . testlogfile)
SUMME=0

den Wert von $SUMME zählst du jetzt in einer Schleife hoch, die so lang ist wie $ADD_LOG werte hat... am ende dividierst du $SUMME durch $DIVISOR
 
Zuletzt bearbeitet:
danke schön, bin noch anfänger, nimms mir nicht übel :)

hochzählen meinst du mit einer for schleife?
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

verdammte scheisse, ich habe keine ahnung wie ich diese schleife machen soll, das ich schlussendlich in $summe eine zahl habe :(
 
Zuletzt bearbeitet:
hi,

vielleicht solltest du mal gucken dass du dir ein kurzes allgemeines Programmier Tutorial oder so durchliest, for-Schleifen sind ja doch recht elementar.

Mit dem was Wolfgang gestern hier schrieb: http://www.unixboard.de/vb3/showpost.php?p=270533&postcount=8 hast du doch eigentlich schon alles was du dafuer brauchst.
Schau dir nochmal
Code:
limit=5; for (( a = 0; a < $limit; a++)); do echo $a; done
an, dann sollte eigentlich schon alles klar sein. Naja, falls dir diese Syntax unbekannt ist, muesstest du das natuerlich nochmal nachlesen um es zu verstehen ;)
Was du noch wissen muesstest, ist dass man fuer Berechnungen let oder (( benutzen muss, wie gestern auch schon angesprochen. Einfach nur SUMME=$SUMME+$ZEILE duerfte nicht funktionieren, aber mit let davor schon.

edit:
ach, mist, man merkt dass ich nicht aus der scripting Ecke komme, in bash geht das natuerlich noch einfacher, du brachst ja gar keine "normale" Zaehlschleife, du kannst dir den Inhalt der Datei auch einfach mit cat ausgeben lassen, und darueber iterieren, ist noch einfacher.
Also so in etwa:
Code:
for i in $(cat test.dat); do echo $i; done

Noch mehr kann ich es dir eigentlich schon nicht mehr vorkauen ;)

mfg,
bytepool
 
Zuletzt bearbeitet:
Ja ich weiss schon das eine for schleife basic wissen ist. es ist nicht so das ich nicht wüste wie eine schleife funktioniert, aber ich wusste nicht wie man in einer schleife jede einzelne zeile miteinander zusammenrechnen kann.

ich hatte noch nie einen kurs, geschweige den von unix oder scripten, ich musste mir alles selbst beibringen, ûnd habe vor gut 2 wochen andgefangen damit. deshalb bin ich auch sehr dankbar um die hilfe, die ihr mir anbietet.

ich werde dies sofort versuchen, dankee!!!
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

aber mit dieser for schleife erreiche ich doch nicht das was ich schlussendlich haben muss???. ich habe das von 2Takter -->
Code:
DIVISOR=$(grep -c . testlogfile)
, das habe ich verstanden und auch schon ausprobiert.

ich muss nur noch wissen wie ich den ganzen inhalt miteinander addieren kann, dies weise ich einer variable zu und schlussenldich wie ihr sagt diese / divisor --> durchschnittswert.
 
Zuletzt bearbeitet:
jup, schau dir einfach nochmal meinen edit einen Post weiter oben an, fuege die einzelnen Elemente zusammen, und voila, da ist deine Loesung ;)

mfg,
bytepool
 
:( :( ;(?(:( ich glaube wir reden aneinander vorbei

Code:
for i in $(cat test.dat); do echo $i; done
das heisst sozusagen das gleiche wie öffne test.dat

ich will das alles im file zusammengezählt wird, dass ich eine ganze zahl habe am schluss :(:(:(:(??

PS: ich weiss es nervt vielleicht, aber ich fahre immer wieder gegen die wand
 
ich glaube wir reden aneinander vorbei
Ja, nee, ich weiss schon was du willst, moechte dir nur eigentlich auch nicht unbedingt die Loesung auf dem Praesentierteller geben, weil das Problem erstens sehr einfach ist, und zweitens sehr elementar, will sagen du hast da wahrscheinlich mehr von wenn du selber drauf kommst. Ich mach das nicht um dich zu aergern oder so ;)

das heisst sozusagen das gleiche wie öffne test.dat
Ehm, ja, nee, kommt drauf an was du unter oeffnen verstehst, im allgemeinen Programmier jargon waere die Antwort darauf "nein".

In jedem schleifen durchlauf wird die naechste Zeile ausgelesen, so dass du damit im eigentlichen body der Schleife arbeiten kannst. Du musst dir natuerlich was anderes als "echo $i" da hinschreiben...

Ich fasse nochmal zusammen:
mit
Code:
((SUMME = $SUMME + $ZEILE ))
kannst du Berechnungen durchfuehren, und mit
Code:
for Zeile in $(cat test.dat); do
   echo $Zeile;
   #oder was immer du hier machen willst
done
kannst du ueber die einzelnen Zeilen iterieren.

Mhhja, und das ist dann eigentlich auch schon die Loesung...

mfg,
bytepool
 
Zuletzt bearbeitet:
das finde ich ja nett von dir das du mich weiter bringen willst, ich habe inzwischen auch begriffen das du in der for schleife willst das ich anstatt echo ... etwas anderes hineinschreibe :) du sagst $summe und $zeile, aber wie sind die definiert, $summe haben wir ja am anfang auf 0 gesetzt, $zeile gibst bis jetzt noch nicht.

ich verzweifle, ich bin scohn den ganzen tag an diesem problem, aber weiss nicht wie ich das scheiss file zusammenzählen kann. auch nach deinen posts.. :(

weshlab nicht ienfach mit awk und dann an sort übergeben? ist das nicht auch ne möglichkeit? ihc habs am anfang doch nur falsch hingeschrieben, weil mir der syntax noch nicht so bekannt ist :(
 
ok hier ist das ganze script vorgekaut

Code:
DATEI="/pfad/zum/file"

SUMME=0
DIVISOR=$(grep -c . ${DATEI})
for i in $(cat ${DATEI}); do SUMME=$(expr $SUMME + $i); done
echo $(expr ${SUMME} / ${DIVISOR})

du müsstest natürlich den pfad anpassen

EDIT: Achtung! Der Ausgabewert ist bereits der Durchschnitt... allerdings berücksichtigt dieser keine Dezimalstellen!

EDIT2: So ist die Schleife etwas übersichtlicher für dich:
Code:
DATEI="/pfad/zum/file"

SUMME=0
DIVISOR=$(grep -c . ${DATEI})
for i in $(cat ${DATEI});
  do
    SUMME=$(expr $SUMME + $i)
  done
echo $(expr ${SUMME} / ${DIVISOR})
 
Zuletzt bearbeitet:
was soll ich sagen, vielen dank an alle. wisst ihr, ich weiss ihr denkt ich bin ein volltrottel, aber für euch sind das basics. ich steh noch ganz am anfang und was mir noch nicht so klar ist:
summe +$1, nimmt er zuerst 0, geht dan in die erste zeile und rechnet den wert der zeile zum akuellen summen wert? anschliessend zur 2., zur 3.?
.
.
.
EDIT (autom. Beitragszusammenführung) :
.

Wenn ich jetzt am schluss vom script noch sagen möchte, das der durchschnitt in eine zusätzliche variable gschrieben werden soll, kann ich das som achen?

Code:
AVERAGE=$(expr ${SUMME} / ${DIVISOR})

hoffenltich stimmt wenigstens das :)
 
Zuletzt bearbeitet:
neee, dass du n volltrottel bist denkt hoffentlich niemand... jeder fing mal bei null an.
genau, er geht zeilenweise vor und addiert den aktuellen wert zur schon bestehenden summe.

und ja, nach deiner änderung enthält dann die variable $AVERAGE den durchschnittswert... aber Achtung! Das ist ein Skript und das bedeutet die Variable ist nicht global sondern nur im Skript vorhanden. Sobald das Skript durchgelaufen ist, ist auch die Variable weg.
 
Hallo

Also sowas löst man nun wirklich eleganter mit Perl oder awk.
Wenngleich es auch mit Shellmitteln geht, solange es um keine Kommastellen geht.
Sonst muss bc ran.

Hier eine schnelle Lösung mit awk, welches AV- alsFließkomma 4 Stellen nach dem Komma Durchschnitt und Zeilenzahl als Ganzzahl ausgibt.

Code:
awk '{c+=$1}END{printf "AV=%.4f\tZeilen%d\n",c/NR,NR}' zahldatei

Willst du nur den Durchschnitt in einer Var haben:
Code:
AV=0;
AV=$(awk '{c+=$1}END{printf "%.4f",c/NR}' zahldatei);

Man kann es auch kompliziert machen und die Shellmittel verwenden. ;)

Übrigens sollte man nicht mehr expr verwenden, das ist ein externer Prozess.
Das läuft merklich langsamer als das Buildin $((...))

merklich meint hier im hundertfachen Bereich

Beispiel:
Code:
$ a=0;time for i in {1..10000}; do a=$(expr $a + $i);done ;echo $a

real    0m20.890s
user    0m4.788s
sys     0m15.049s
50005000
wolle@Nietzsche:/tmp
$ a=0;time for i in {1..10000}; do a=$((a + $i));done ;echo $a

real    0m0.248s
user    0m0.248s
sys     0m0.000s
50005000

So nun könnt ihr selbst vergleichen!

Gruß Wolfgang
 
Hallo Wolfgang

Vielen Dank für deinen Betrag. Ich habe aus Gewohnheit "expr" verwendet, da es so in meinem Grundlagen Buch steht. Ich werde von nun an $((...)) verwenden, da man wirklich anhand deinem Beispiel sehen kann, dass es schneller ist.

Ich möchte deine "awk-Lösung" komplett verstehen --> {c+=$1}, was macht das genau? Ich habe schon mehrere Bücher durchschaut, und finde den Begriff c+ nicht. Könntest du oder ihr mir in kurzen Worten beschreiben, was die Zeile macht?

Danke an euch alle!
 
Hallo
c+=$1 ist das Gleiche wie c= c +$1.
Addiert also $1 zu dem Inhalt der Variable c und speichert diese wieder in c.

Am Ende gebe ich mit printf im Fließkommaformat die Summe geteilt durch Anzahl der Zeilen ( Variable NR) aus.

Gruß Wolfgang
 
Achso, super, wusste nicht, dass man das so abkürzen kann. Meine allerletzte Frage, wie wurde die Variable NR definiert? Wie weiss die Shell das NR die Anzahl Zeile ist?

Gruss Doonot
 

Ähnliche Themen

Keine grafische Oberfläche (Debian Installation)

grep + regex zum Log parsen

CentOS 7 Grafikkarte auswählen

ca. 1200 PDF-Dateien auslesen und bestimmte Daten in eine CSV-Datei speichern

Maskiertes Suchen, Ersetzen und Rechnen in access.log vor weitere Bearbeitung

Zurück
Oben