• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

[SOLVED] Filtern mit grep

byron1778

Hacker
Hallo Forum!

Ich haette folgendes Problem und bin mir nicht sicher, ob man es mit grep und einem awk oder nur einem grep loesen kann!

Folgende Zeile aus einem Nagios - File

Code:
May  4 10:37:08.13755 xxx xxxxxx[18458:t@196       ]/error: [user:xxx:xxx@xxx] - Transaction map 37 -> N/A market 0

Wenn jetzt diese Zeile kommt (die Zahl kann sich aber stets veraendern!), dann soll er keinen Error darstellen auf der Nagios - Oberflaeche!
Wichtig hierbei ist aber, dass es vll. noch andere Errors mit Transaction map geben kann (wir haben leider keine Liste ueber alle aehnlichen Fehlermeldungen!).

Deswegen wuerde ich nun gerne ein Konstrukt basteln, dass ungefaehr so aussieht

Code:
tail -200 /usr/orc/log/xxxlog |grep -c error | grep -vi " transaction map" && N/A market 0

Gibt es eine Moeglichkeit so ein Abfragekonstrukt zu konstruieren, welches mit einem && oder mit einem or arbeitet?
Vll. funktioniert soetwas mit einem awk - Statement?

Danke schon mal fuer jede Hilfe!
 
A

Anonymous

Gast
Klassischer Fall für AWK; Einführung erste Hilfe und Links gibts hier

Wenn ihr nicht ganz klar kommt, dann hier noch mal mit ca 10 Orgialzeilen melden und genau definieren was wie gefiltert werden soll und was nicht. Hätte aber erst heute Abend für so was Zeit.

robi
 
OP
B

byron1778

Hacker
Hallo!

Danke Dir vielmals fuer den Tipp mit awk.
Da muss ich mich wohl laenger einlesen in diese Sprache!

So sehen die Zeilen aus
Dort, wo die xxx stehen, sind User und Serverangaben, die habe ich ersetzt, ich hoffe, dass geht in Ordnung!

Code:
May  4 09:15:04.96834 xxx bhsprod[18458:t@139       ]/error: [user:xxx:xxx@xxx] - Transaction map 15 -> QD10658713 market 1
May  4 09:15:04.96838 xxx bhsprod[18458:t@139       ]/error: [user:xxx:xxx@xxx] - Transaction map 16 -> QD10658713 market 1
May  4 09:16:19.29326 xxx bhsprod[18458:t@139       ]/error: [user:xxx:xxx@xxx] - Transaction map 7 -> QD10658709 market 1
May  4 09:16:19.29331 xxx bhsprod[18458:t@139       ]/error: [user:xxx:xxx@xxx] - Transaction map 8 -> QD10658709 market 1
 
A

Anonymous

Gast
aus diesen 4 Zeilen ist es schwierig da wirklich was 100% passendes zusammenzubauen. Das Problem ist, man muss die einzelnen Zeilen in solchen Listen zu Feldern zusammenbauen können, die man dann recht komfortabel auf den Inhalt prüfen kann. Um das in Felder einteilen zu können braucht man aber Feldtrenner, ich habe hier mal die Normalen also " " und oder "\t" angenommen. Wenn sich jetzt aber in einem Feld zB mal zwei Worte mit einem Leerzeichen getrennt befinden, kommt die ganze Zeile schon durcheinander. Und das passiert viel schneller als man manchmal denken kann. Nicht wenige Scripte hat es schon zerrissen nur weil es eine Umstellung von Sommer- auf Winterzeit gab oder weil irgendwie die LANG-Variablen der Shell sich geändert hat. Anderes Datumformat, :???: :???: :???: Um sowas richtig zu machen bräuchte man desshalb da am Besten zum Test einen Auszug aus allen oder möglichst vielen möglichen Kombinationen. Alle Zeilen müssten sich zumindestens am Anfang alle in gleiche Felder mit definierter Bestimmung aufteilen lassen, oder man müsste an Hand eines Feldes erkennen, das diese Zeile einen andere Feldanzahl oder Feldbedeutung hat. Das ist das Problem bei solchen Logdateien.

Aber egal, ich hab mal was zusammengeschrieben, von dem ich glaube man könnte für das scheinbar kleine Problem ausreichen und man könnte es mit etwas guten Willen durchaus auch noch anpassen. ;)

Code:
awk '$6 ~/error:/{TYPE=$9 $10 ; MAP=$14 $15 ; if ((TYPE=="Transactionmap")&&(MAP=="market0")) next ; else print $0}'

Übergeben werden die Daten entweder über einen Pipe oder als Datei einfach den Dateinamen dahinter setzen. Raus kommt das Gefilterte auf der Standardausgabe.

Erklärung:
Feldtrenner also Leerzeichen.
1. es wird getestet ob im 6. Feld die Zeichenkombination "error:" vorkommt, sonst wird gleich mit der nächsten Zeile weitergemacht .
2. ist "error:" im 6. Feld gefunden wird aus Feld 9+10 und aus Feld 14+15 jeweils eine Variable gemacht, indem einfach die beiden Feldinhalte ohne Feldtrenner zusammengeschrieben werden.
TYPE enthält dann dadurch bei deinen Testreihen den Wert "Transactionmap"
und MAP den Inhalt "market???" je nach Inhalt von Feld 15
3. Jetzt wird getestet ob in TYPE auch wirklich "Transactionmap" und zusätzlich in MAP "market0" steht, und nur in diesem einem Fall passiert dann gar nichts, es wird durch next die nächste Zeile der Eingabe zur Weiterbearbeitung geladen und damit weitergemacht
4. In allen anderen Fällen wird die gesamte Zeile ausgegeben.

Das Ergebnis sollte also alles sein, was im Feld 6 "error:" enthält und nicht "Transaction map .......market 0" ist.

robi
 

abgdf

Guru
@byron1778: Du wolltest doch neulich komplexe Datenstrukturen (wie Hashes von Hashes) in Perl einsetzen:

http://www.linux-club.de/viewtopic.php?f=21&t=103564

Und jetzt kommst Du nicht einmal mit einer einfachen grep-Zeile zurecht und meinst, Du müßtest erstmal awk lernen, um ein paar Informationen aus einer Textdatei zu extrahieren? :shock:
 

framp

Moderator
Teammitglied
Warum nicht einfach mit einem regulären Ausdruck?
perl -n -e 'if (/error: \[.+\:.+\:.+\@.+\] - Transaction map.*market 0/) { print;}'
Es wird getested ob "/error: [user:xxx:xxx@xxx]" in der Zeile steht und dann von "Transaction map" sowie "market 0" gefolgt wird.
 
A

Anonymous

Gast
framp schrieb:
Warum nicht einfach mit einem regulären Ausdruck?
perl -n -e 'if (/error: \[.+\:.+\:.+\@.+\] - Transaction map.*market 0/) { print;}'
Regulärer Ausdruck geht auch, nur wenn ich byron1778 richtig verstanden habe, zeigt deiner genau das, was er wegfiltern will. ;)

Geht auch nur mit grep und Regex. Die Kunst ist dabei nur wie eine Woche später den Befehl selbst wieder zu verstehen, damit man nochmal kleine Änderungen daran machen kann. ;) ;) ;)
Mit reiner grep Befehlsverkettung ohne Reguläre Ausdrücke habe ich es jedenfalls auf Anhieb nicht geschafft.

robi
 
OP
B

byron1778

Hacker
Hallo!

add abgdf: Ja, das Problem besteht darin, dass ich zwar sehr gerne mit Perl und co. etwas schreibe, aber ich es leider nicht taeglich brauche, somit kommt es dann oftmals vor, dass man die leichtesten Sachen nicht mehr hinbekommt und ich mir stundenlang den Kopf darueber zerbrechen muss, wie denn das gehen koennte, genauso war es hier auch!

Man kommt bei den Sachen so leicht aus der Uebung, unfassbar!

add robi: Du hast vollkommen recht, genau dieser Ausdruck soll am Ende ignoriert werden. Ich habe das bei deinem Code folgendes getan, einfach das print weggenommen, hoffe, dass das so richtig ist, vom Ergebnis her ja, aber auch nur, weil er es ja nicht mehr "printet", aber auch wenn er es nur nciht mehr "printet" ignoriert er es ja leider nicht ... ?!
Lieber waere es mir, wenn er einfach weitermacht und alle anderen errors ausgibt, nur diesen einen nicht mit dem Transaction map!
 
OP
B

byron1778

Hacker
Ich konnte hoffentlich das Problem nun so loesen mit Eurer Hilfe!

Code:
cat test.txt | grep /error: | egrep -ve "user:.*Transaction map [0-9].* -> N/A market [0-9].*"

Jetzt sollte er genau diesen String ignorieren und nicht auswerten!
Alle anderen Errors, seien sie auch fast so aehnlich werden hingegen angezeigt!

Danke Euch vielmals!
 

framp

Moderator
Teammitglied
robi schrieb:
Regulärer Ausdruck geht auch, nur wenn ich byron1778 richtig verstanden habe, zeigt deiner genau das, was er wegfiltern will. ;)
Dann muss man nur die Logik mit einem ! umdrehen ;-)
Mit reiner grep Befehlsverkettung ohne Reguläre Ausdrücke habe ich es jedenfalls auf Anhieb nicht geschafft.
Das hat byron1778 basierend auf unseren Diskussionen selbst hinbekommen - mit grep, mit regulärem Ausdruck, ohne awk und ohne perl. Ziel erreicht :smile:
 
Oben