awk/sed Zeilen bei der Uhrzeit 3 Minuten auseinanderliegt löschen

X

xenomorph150

Grünschnabel
Hallo Leute,

ich habe ein Problem mit einer Logdate.
Ich prüfe mit einem Skript das ich laufen lasse alle 3 Minuten ob ein System noch online ist. Ich lasse mir folgendes ausgeben:

z.b:

09/07/08 13:09:01
09/07/08 13:12:02
09/07/08 13:15:01
09/07/08 13:18:01
09/07/08 13:21:01
09/07/08 13:48:01
09/07/08 13:51:01
09/07/08 15:15:01
09/07/08 15:18:01
09/07/08 15:21:01
09/07/08 15:24:01

Jetzt möchte ich aber diese Logdateien nochmal überarbeiten lassen, also sollen alle Einträge bei welcher die Zeit mehr als drei Minuten auseinanderliegen gelöscht werden (3 Minuten Abfrage Rhythmus).
Dabei sollen aber die erste und die letzte Zeile stehen bleiben, damit ich immer weiß von wann bis wann das Ding funktionierte - und wann es abgeschaltet war.

So sähe also mein Ergebniss am besten aus:

09/07/08 13:09:01
09/07/08 13:21:01
09/07/08 13:48:01
09/07/08 13:51:01
09/07/08 15:15:01
09/07/08 15:24:01

Hat jemand eine Idee wie das gehen könnte?
Ich müsste also erstmal pro Zeile das Datum abtrennen anfangs, dann die Stellen nach dem 2ten Doppelpunkt (der Minutenzähler) mit dem der nächsten Zeile vergleichen ob der 3 Minuten unterschied hat - und wenn ja ihn löschen - wenn DANACH noch einer kommt der 6 Minuten unterschied zu dem Orginal hat....

..Hm... Irgendwie ist dieses Verfahren noch nicht optimal o.o'.

Hat jemand vielleicht eine bessere Idee und auch eine Umsetzung dafür?

Danke,
Xeno
 
Hi,

Jetzt möchte ich aber diese Logdateien nochmal überarbeiten lassen, also sollen alle Einträge bei welcher die Zeit mehr als drei Minuten auseinanderliegen gelöscht werden (3 Minuten Abfrage Rhythmus).
[...]
So sähe also mein Ergebniss am besten aus:

09/07/08 13:09:01
09/07/08 13:21:01
09/07/08 13:48:01
09/07/08 13:51:01
09/07/08 15:15:01
09/07/08 15:24:01

das macht keinen Sinn. Aber ich vermute, dass du genau das Gegenteil meinst, dass alle Zeilen behalten werden sollen, die einen Interval > 3 haben...

Aber auch das macht mit deinem Beispiel keinen Sinn:
09/07/08 13:48:01
09/07/08 13:51:01
Nun gut, ich bin mal davon ausgegangen dass du das meintest, und habe da zum Spass ein kleines Skript fuer geschrieben. Einfacher ginge es aber wohl in Perl.

Code:
#!/bin/bash

out_file="filtered.txt"
in_file="logs.txt"

function parse_new_line
{
    date="$(echo $line | awk -F' ' '{print $1}')"
    time="$(echo $line | awk -F' ' '{print $2}')"

    hours="$(echo $time | awk -F':' '{print $1}')"
    minutes="$(echo $time | awk -F':' '{print $2}')"
    seconds="$(echo $time | awk -F':' '{print $3}')"

    hours=${hours#0}
    minutes=${minutes#0}
    seconds=${seconds#0}
}

function set_old
{
    old_line="$line"
    old_date="$date"
    old_time="$time"

    old_hours="${hours}"
    old_minutes="${minutes}"
    old_seconds="${seconds}"
}

function add_line
{
    echo $line #>> $out_file
}

read line < $in_file
add_line

parse_new_line
set_old

while read line; do
    parse_new_line

    if [ ${hours} -eq ${old_hours} ]; then
        next_interval=$((old_minutes + 3))

        if [ $minutes -gt $next_interval ]; then
            add_line
        fi
    else
        add_line
    fi

    set_old
done < $in_file

line=$(tail -n1 $in_file)
add_line
Dabei wird jetzt weder das Datum beachtet, noch Stundenueberlaeufe. Um das Skript wirklich perfekt zu machen, muesstest du noch eine ganze Menge kleiner if Abfragen hinzufuegen.

Edit:
Ausserdem sollte man beachten, dass ich das jetzt so auf die Schnelle geschrieben hab, und das Skript sicherlich keinen Schoenheitswettbewerb gewinnen wird. Variablennamen, Konsistenz, etc. kann alles noch besser.

mfg,
bytepool
 
Zuletzt bearbeitet:
Hallo bytepool,

tut mir leid ich glaube wir haben ein wenig aneinander vorbei geredet.
Hier z.b. ein neuer Log:

09/07/09 08:57:01
09/07/09 09:00:02
09/07/09 09:03:02
09/07/09 09:06:02
09/07/09 09:09:02
09/07/09 09:12:02
09/07/09 09:15:02
09/07/09 09:18:02
09/07/09 09:21:02
09/07/09 09:24:03
09/07/09 09:27:02
09/07/09 09:30:01
09/07/09 09:33:03
09/07/09 09:36:02
09/07/09 09:39:02
09/07/09 09:42:03
09/07/09 09:45:05
09/07/09 09:48:02
09/07/09 09:51:05
09/07/09 09:54:03
09/07/09 09:57:02
09/07/09 10:09:03
09/07/09 10:12:03
09/07/09 10:15:02
09/07/09 10:18:02
09/07/09 10:21:03
09/07/09 10:24:03
09/07/09 10:27:02
09/07/09 10:30:07
09/07/09 10:33:03
09/07/09 10:36:05
09/07/09 10:39:03
09/07/09 10:42:02
09/07/09 10:45:05
09/07/09 10:48:03
09/07/09 10:51:02
09/07/09 10:54:02
09/07/09 10:57:05
09/07/09 11:00:04
09/07/09 11:03:05
09/07/09 11:06:02
09/07/09 11:33:04
09/07/09 11:36:02
09/07/09 11:39:03
09/07/09 11:42:02
09/07/09 11:45:03
09/07/09 11:48:02
09/07/09 11:51:03
09/07/09 11:54:02
09/07/09 11:57:03
09/07/09 12:00:02
09/07/09 12:03:02
09/07/09 12:06:04
09/07/09 12:09:04
09/07/09 12:12:03
09/07/09 12:15:03
09/07/09 12:18:02
09/07/09 12:21:02
09/07/09 12:24:03
09/07/09 12:27:02
09/07/09 12:30:02
09/07/09 12:33:04
09/07/09 12:36:02

Es sollen IMMER die "Anfangszeit" und die "Endzeit" ausgegeben werden hintereinander - oder sogar so: "Anfangszeit - Endzeit".
Definiert sind Anfangszeit und Endzeit als Punkte die nicht länger als 3-5 Minuten auseinanderliegen (ich sag mal 5 als Toleranz wenn schwere Netzwerklast vorliegt, man sieht ja dass er mal eine Sekunde oder so mal hin und wieder mehr braucht).

In dem fall wäre aus der Tabelle oben also als Ergebnis:

09/07/09 08:57:01
09/07/09 09:57:02
09/07/09 10:09:03
09/07/09 11:06:02
09/07/09 11:33:04
09/07/09 12:36:02

oder sogar wenns möglich ist:

09/07/09 08:57:01 - 09/07/09 09:57:02
09/07/09 10:09:03 - 09/07/09 11:06:02
09/07/09 11:33:04 - 09/07/09 12:36:02

diese Sachen ausgegeben.
Damit ich immer weiß von wann bis wann das System funktionierte.

Ist sowas möglich? Vielen Dank schon mal für deine Hilfe!


Gruß,

Nico
 
Hi,

Definiert sind Anfangszeit und Endzeit als Punkte die nicht länger als 3-5 Minuten auseinanderliegen (ich sag mal 5 als Toleranz wenn schwere Netzwerklast vorliegt, man sieht ja dass er mal eine Sekunde oder so mal hin und wieder mehr braucht).

an deinen Erklaerungskuensten musst du wirklich noch arbeiten, das ist immer noch Falsch. Wenn ich das so anwende wie du es schreibst, bekommst du jede Menge kleine 3 Minuten Intervalle; die Logdatei wuerde sich kaum veraendern.

Mit dem Hinweis auf Anfangszeit und Endzeit, zusammen mit den Beispielen, bin ich jetzt aber, denke ich, dahinter gestiegen was du eigentlich genau willst.

Um dein Problem mal korrekt zu formulieren:

Anhand von einer Logdatei sollen "uptime" Intervalle eines bestimmten Servers gefunden werden. In Intervallen von x Minuten gibt es einen Logeintrag. Wenn ein Logeintrag ausgelassen wird, definiert dies das Ende des gesuchten "uptime" Intervalls, wovon jeweils nur die Anfangszeit und die Endzeit gespeichert werden soll. Der folgende Logeintrag beginnt das naechste "uptime" Intervall.

Richtig?

Was passt dir an dem Skript jetzt nicht? Ist doch eine prima Vorlage, die Anpassung an deine Vorgaben erfordert noch ein bisschen eigene Arbeit, ist aber eigentlich ziemlich einfach.
Im Grunde musst du nur noch eine Zeile hinzufuegen, und dann noch ein paar Randbedingungen ueberpruefen.

Das darfst du aber selbst machen, das ist mir zu langweilig. ;)

Nebenbei, fuer die Auflistung der Beispiele koenntest du Code-Bloecke benutzen, das macht deine Posts lesbarer.

Edit:
Im uebrigen ist die saubere Formulierung des Problems bereits der erste Schritt zur Problemloesung. Wenn die Problemstellung von Anfang an wie von mir formuliert gewesen waere, wuerde mein Skript ganz anders aussehen; deutlich klarer und strukturierter, weil die Konzepte klar waeren.

Edit2:
Wie hat Daniel Jackson das mal so schoen in Software Abstractions (MIT Press) formuliert?
"Software is built on abstractions. Pick the right ones, and programming will flow naturally from design; modules will have small and simple interfaces; and new functionality will more likely fit in without extensive reorganization. Pick the wrong ones, and programming will be a series of nasty surprises."

mfg,
bytepool
 
Zuletzt bearbeitet:
Hi bytepool,

Verzeihung für die Unanehmlichkeiten, ich denke wir haben irgendwie aneinander vorbei geredet. Ich habe nach einigem Nachdenken eine eigene Lösung für das Problem gefunden und poste sie hiermit nun für den Fall das jemanden das helfen würde.

mk_log.sh
Code:
#! /bin/sh
tr -d '\015\032' < $1 | sed -e "/^ *$/d" > $1_tr  # Win <> Lin Uebersetzung und Leerzeichen Entfernung
gawk -f mk_log_primer.awk $1_tr > $1_primer       # Log Primer trennt Datum und Uhrzeit auf
gawk -f mk_log_coder.awk $1_primer > $1_cod       # Log Coder erzeugt fertige Logfile

rm $1_tr
rm $1_primer


mk_log_primer.awk
Code:
#14.07.09 mk_log_primer.awk

#------------------------------------------------------------------------------
BEGIN{ idx=1; FS=" "}
#------------------------------------------------------------------------------
{
  datum[idx]=$1
  zeit[idx]=$2
  idx++
}
#------------------------------------------------------------------------------
END{ 
i=1

do 
{
	printf "%s\n",zeit[i]
       i++
} 
while (i < idx)
}
#------------------------------------------------------------------------------


#------------------------------------------------------------------------------


mk_log_coder.awk
Code:
#15.07.09 mk_log_coder.awk

#------------------------------------------------------------------------------
BEGIN{ idx=1; FS=":"}
#------------------------------------------------------------------------------
{
  stunden[idx]=$1
  minuten[idx]=$2
  sekunden[idx]=$3
  idx++

}
#------------------------------------------------------------------------------
END{ 
i=1
	printf "%s%s%s%s%s%s","Anfang: ", stunden[i],":",minuten[i],":",sekunden[i] 

do 
{
	diffstd=stunden[i+1]-stunden[i]

	if (diffstd==0)
	{
	differenz=minuten[i+1]-minuten[i]


	if (differenz>3)
	{
		printf "%s%s%s%s%s%s\n"," - Ende: ", stunden[i],":",minuten[i],":",sekunden[i] 
		printf "%s%s%s%s%s%s","Anfang: ", stunden[i+1],":",minuten[i+1],":",sekunden[i+1]
	}
	else
	{
		if (differenz<0)
		{
			printf "%s%s","Differenz < 0", " "
		}
	}
	}

	if (diffstd>0)
	{
	differenz=minuten[i+1]-minuten[i]
	differenz=(diffstd*60)+differenz

	if (differenz>3)
	{
		printf "%s%s%s%s%s%s\n"," - Ende: ", stunden[i],":",minuten[i],":",sekunden[i] 
		printf "%s%s%s%s%s%s","Anfang: ", stunden[i+1],":",minuten[i+1],":",sekunden[i+1]
	}
	else
	{
		if (differenz<0)
		{
			printf "%s%s","Differenz < 0", " "
		}
	}
	}
	
	if (diffstd<0)
	{
		printf "%s%s%s%s%s%s\n"," - Ende: ", stunden[i],":",minuten[i],":",sekunden[i]
	}

       i++
} 
while (i < idx)
}
#------------------------------------------------------------------------------


#------------------------------------------------------------------------------




Beispielsdatei:
Code:
09/07/08 12:54:01
09/07/08 12:57:01
09/07/08 13:00:01
09/07/08 13:03:01
09/07/08 13:05:01
09/07/08 13:06:01
09/07/08 13:09:01
09/07/08 13:36:01
09/07/08 13:39:01
09/07/08 13:42:01
09/07/08 13:48:01
09/07/08 13:51:01
09/07/08 13:54:01
09/07/08 14:18:01

09/07/08 14:33:01
09/07/08 14:36:01


Ausgabe:
Code:
Anfang: 12:54:01 - Ende: 13:09:01
Anfang: 13:36:01 - Ende: 13:42:01
Anfang: 13:48:01 - Ende: 13:54:01
Anfang: 14:18:01 - Ende: 14:18:01
Anfang: 14:33:01 - Ende: 14:36:01



Grüße,

Nico


EDIT: Noch ein Fehler im Code beseitigt ^^
 
Zuletzt bearbeitet:

Ähnliche Themen

Mit AWK verschiedene Felder verschiedener Zeilen vergleichen

Mein Server versendet SPAM in Massen

Zeilen separieren

Finde Fehler im Code nicht

CSV Datei mit sed manipulieren/optimieren/ergänzen

Zurück
Oben