shell script was zwei zeilen parsen tut

Du suchst ein Programm für einen bestimmten Zweck?
Antworten
ren22

shell script was zwei zeilen parsen tut

Beitrag von ren22 » 19.12.2016 22:41:29

Hallo,

wie kann man am schnellsten und elegantesten über zwei Zeilen Parsen ?

such regex'es sind: "info:","A IN", "AAAA IN"

Angenommen im log steht:

Dec 17 22:00:36 server1 unbound: [93528:0] info: 10.10.10.5 http://www.google-analytics.com. A IN
Dec 17 22:00:36 server1 unbound: [93528:0] info: 10.10.10.5 http://www.google-analytics.com. AAAA IN

ich würde zuerst nach "info:" suchen und dann nach "A IN", und setzte eine Variable auf "true", wenn beides zustimmt.
Danach würde ich schauen ob die Variable auf "true" steht, und wieder nach "info: und dann nach "AAAA IN" suchen, wenn das auch zustimmt
gebe eine Meldung aus. Was auch wichtig ist, dass die Zeilen nacheinander folgen und

Dec 17 22:00:36 server1 unbound: [93528:0] info: 10.10.10.5 http://www.google-analytics.com. A IN
bla foo bar bla bla foo bar
Dec 17 22:00:36 server1 unbound: [93528:0] info: 10.10.10.5 http://www.google-analytics.com. AAAA IN

dann nicht eine Erfolgs Meldung ausgegeben wird, dass das gesuchte auf zwei Zeilen zutrifft. Da zwischen den zeilen "http://www.google-analytics.com" , bla foo bar bla bla foo bar vorkommt und somit nicht mehr zwei nacheinander folgende Zeilen sind.

Jemand eine Idee was die schnellste und eleganteste Lösung dafür wäre?

hier mein unfertiges shell script:

Code: Alles auswählen

#!/bin/sh

#Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 www.google-analytics.com. A IN
#Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 www.google-analytics.com. AAAA IN
searchString1="info:" #awk '{print "$7"}')
searchString2="A IN" #awk '{print $10 " " $11}')"
searchString3="AAAA IN" #awk '{print $10 " " $11}')"
searchString4="domainname" #awk '{print $9}')"

firstlinefound=false
secondlinefound=false

while read -r line
do
	#set -x
	
	#set the domainname variable
	#searchString4=$(echo "$line" | awk '{print $9}')
	
	#search for "info:"
	if [ "$searchString1" == "$(echo "$line" | awk '{print $7}')" ] \
	&& [ "$searchString2" == "$(echo "$line" | awk '{print $10 " " $11}')" ]; then
		#set firstlinefound to true
		firstlinefound=true
		#save the domain before overwriting in the next read loop
		#olddomain=$(echo $searchString4)
		olddomain=$(echo "$line" | awk '{print $9}')
		#go to read next line on first found
		continue
	fi

#	#if match the second line with olddomain from the previous line go further
#	if [ "$olddomain" == $(echo "$line" | awk '{print $9}') ] && [ "$firstlinefound" == true ] \
#	&& [ "$(echo "$line" | awk '{print $9}')" == $searchString4 ]; then
#		#search for "info:"
#		if [ "$searchString1" == "$(echo "$line" | awk '{print $7}')" ]; then
		#search for "AAAA IN"
#			if [ "$searchString3" == "$(echo "$line" | awk '{print $10 " " $11}')" ]; then
#			secondlinefound=true
#			fi
#		fi
#	fi
	#reset olddomain and firstlinefound if not found on the second read line attempt
	if [ ! "$olddomain" == $(echo "$line" | awk '{print $9}') ]; then
		olddomain=""
		firstlinefound=false
		continue
	fi
	
	#print a match
	if [ "$firstlinefound" == true ] && [ "$secondlinefound" == true ]; then
		echo "match: $searchString4"
		#reset variables
		firstlinefound=false
		secondlinefound=false
		searchString4=""
	fi
done < 234
$cat 234

Code: Alles auswählen

Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 www.gravatar.com. AAAA IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 i.stack.imgur.com. A IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 ssum-sec.casalemedia.com. AAAA IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 static.adzerk.net. A IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 static.adzerk.net. AAAA IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 www.google-analytics.com. A IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 www.google-analytics.com. AAAA IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 edge.quantserve.com. A IN
123 433 324 468 34 5 2562 832 32 2 626 8376 222
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 edge.quantserve.com. AAAA IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 b.scorecardresearch.com. A IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 b.scorecardresearch.com. AAAA IN
und so sollte das script matchen :
Dec 17 22:00:36 sense unbound: [93528:0] info: 192.168.123.64 http://www.gravatar.com. AAAA IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 192.168.123.64 i.stack.imgur.com. A IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 192.168.123.64 ssum-sec.casalemedia.com. AAAA IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 192.168.123.64 static.adzerk.net. A IN <<<<<---------------------------MATCH
Dec 17 22:00:36 sense unbound: [93528:0] info: 192.168.123.64 static.adzerk.net. AAAA IN <<<<<---------------------------MATCH
Dec 17 22:00:36 sense unbound: [93528:0] info: 192.168.123.64 http://www.google-analytics.com. A IN <<<<<---------------------------MATCH
Dec 17 22:00:36 sense unbound: [93528:0] info: 192.168.123.64 http://www.google-analytics.com. AAAA IN <<<<<---------------------------MATCH
Dec 17 22:00:36 sense unbound: [93528:0] info: 192.168.123.64 edge.quantserve.com. A IN <<<<<---------------------------KEIN !!! MATCH
123 433 324 468 34 5 2562 832 32 2 626 8376 222
Dec 17 22:00:36 sense unbound: [93528:0] info: 192.168.123.64 edge.quantserve.com. AAAA IN <<<<<---------------------------KEIN !!! MATCH
Dec 17 22:00:36 sense unbound: [93528:0] info: 192.168.123.64 b.scorecardresearch.com. A IN <<<<<---------------------------MATCH
Dec 17 22:00:36 sense unbound: [93528:0] info: 192.168.123.64 b.scorecardresearch.com. AAAA IN <<<<<---------------------------MATCH

Danke

Benutzeravatar
heisenberg
Beiträge: 3473
Registriert: 04.06.2015 01:17:27
Lizenz eigener Beiträge: MIT Lizenz

Re: shell script was zweil zeilen parsen tut

Beitrag von heisenberg » 19.12.2016 23:48:12

Na wenn das - Multiline-RegEx - mal nicht die Königsdisziplin für Perl ist :)

Code: Alles auswählen

perl -e '$/=undef;$_=<>;while(/^([^\n]* info: [^\n]* ([^\n]*) A IN\n[^\n]* info:[^\n]*\2 AAAA IN)/mg) {print($1,"\n");}' 234
Ausgabe:

Code: Alles auswählen

Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 static.adzerk.net. A IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 static.adzerk.net. AAAA IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 www.google-analytics.com. A IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 www.google-analytics.com. AAAA IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 b.scorecardresearch.com. A IN
Dec 17 22:00:36 sense unbound: [93528:0] info: 10.10.10.5 b.scorecardresearch.com. AAAA IN
Aber awk ist noch kürzer und gefällt mir besser:

Code: Alles auswählen

awk '/info:.* A IN$/{U=$(NF-2);L=$0;next} /info:.*AA IN$/{U2=$(NF-2);if(U==U2&&L)print L"\n"$0} {L=""}' 234
... unterhält sich hier gelegentlich mangels wunschgemäßer Gesprächspartner mal mit sich selbst.

Benutzeravatar
Meillo
Moderator
Beiträge: 8782
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: shell script was zweil zeilen parsen tut

Beitrag von Meillo » 20.12.2016 06:55:59

heisenberg hat geschrieben:Na wenn das - Multiline-RegEx - mal nicht die Königsdisziplin für Perl ist :)
Aber awk ist noch kürzer und gefällt mir besser:
Na sowas, es besteht ja doch noch Hoffnung bei dir! Nur weiter so! :mrgreen: *SCNR*
Use ed once in a while!

uname
Beiträge: 12046
Registriert: 03.06.2008 09:33:02

Re: shell script was zweil zeilen parsen tut

Beitrag von uname » 20.12.2016 09:16:04

Die awk-Lösung gefällt mir auch ganz gut. Vor allem weil es die Aufgabe besser löst als der Threadstarter ausdrücken konnte was er überhaupt benötigt ;-)

Benutzeravatar
heisenberg
Beiträge: 3473
Registriert: 04.06.2015 01:17:27
Lizenz eigener Beiträge: MIT Lizenz

Re: shell script was zweil zeilen parsen tut

Beitrag von heisenberg » 20.12.2016 09:34:08

Also die Anfrage war im Vergleich zu dem, was sonst so geschrieben wird, ja schon ziehmlich präzise. Da fällt es leicht, eine passende Antwort zu schreiben. Fehlte nur noch eine gewünschte Beispielausgabe.

Aber das was er will, ist wohl das:

Code: Alles auswählen

awk '/info:.* A IN$/{U=$(NF-2);next} /info:.*AA IN$/{U2=$(NF-2);if(U==U2)print U} {U=""}' 234
oder etwas übersichtlicher:

myprogram.awk

Code: Alles auswählen

#!/usr/bin/awk -f

/info:.* A IN$/   {
  U=$(NF-2)
  next
  } 

/info:.*AA IN$/  {
  U2=$(NF-2)
  if(U==U2) print U
  } 

  {
  U=""
  }
Ausgabe

Code: Alles auswählen

static.adzerk.net.
www.google-analytics.com.
b.scorecardresearch.com.
Zuletzt geändert von heisenberg am 29.12.2016 19:17:42, insgesamt 3-mal geändert.
... unterhält sich hier gelegentlich mangels wunschgemäßer Gesprächspartner mal mit sich selbst.

ren22

Re: shell script was zwei zeilen parsen tut

Beitrag von ren22 » 20.12.2016 11:14:05

@ Danke an alle , besonders an heisenberg :D

@uname: im Grunde ging/geht es mir darum, dass wenn zwei Zeilen nacheinander folgen,wichtig nacheinander, und die gleiche domain enthalten ist, sollte es ein "match" ausgeben,
da "info:" und "A IN" in der ersten Zeile verkommen und "info:" und "AAAA IN" in der Zweiten, kann man damit sehr leicht matchen. Also es soll in der ersten Zeile
"info:" und "A IN" und in der zweiten Zeile info: und "AAAA IN" gemacht werden, ist das der Fall, ohne das zwischen den beiden Zeilen noch eine andere steht, print. Match.
..ich weiß, jeder versteht es anders :D

@heisenberg: Kannst du mir noch erklären, was genau dein geniales AWK Script genau macht ?

Danke

Benutzeravatar
heisenberg
Beiträge: 3473
Registriert: 04.06.2015 01:17:27
Lizenz eigener Beiträge: MIT Lizenz

Re: shell script was zwei zeilen parsen tut

Beitrag von heisenberg » 20.12.2016 11:57:24

Ich habe es oben nochmal etwas übersichtlicher dargestellt und würde Dich bitten es Dir selbst etwas genauer anzuschauen, vielleicht verstehst Du ja von selbst, wie es funktioniert. Falls Du nicht drauf kommst, kannst Du ja 1-2 Wochen warten, dann schreibe ich die Erklärung dazu.
... unterhält sich hier gelegentlich mangels wunschgemäßer Gesprächspartner mal mit sich selbst.

uname
Beiträge: 12046
Registriert: 03.06.2008 09:33:02

Re: shell script was zwei zeilen parsen tut

Beitrag von uname » 20.12.2016 12:22:04

wichtig nacheinander, und die gleiche domain enthalten ist
die gleiche Domain habe ich im Ursprungspost nicht herausgelesen. Wobei eigentlich stand es ja in deinem Code. Mein Fehler.
In der Lösung wurde es entsprechend korrekt umgesetzt:

Code: Alles auswählen

U=$(NF-2)
U2=$(NF-2)
if(U==U2)

ren22

Re: shell script was zweil zeilen parsen tut

Beitrag von ren22 » 20.12.2016 13:25:22

oder etwas übersichtlicher:

myprogram.awk

Code: Alles auswählen

#!/usr/bin/awk -f

/info:.* A IN$/ 
  {
  U=$(NF-2)
  next
  } 

/info:.*AA IN$/
  {
  U2=$(NF-2)
  if(U==U2) print U
  } 

  {
  U=""
  }
ich glaub ich hab das so ein wenig mit AWK verstanden, hatte mich bisher noch nie so wirklich mit AWK auseinander gesetzt, aber jetzt in diesem Beispiel, habe ich wieder ein Menge gelernt, ich wusste nicht das man viele Zeilen Code mit AWK in einer Zeile verwandeln kann.
Also wenn ich das richtig verstehe suchst du mit AWK erst nach info und A IN, bis Zeilenende, wenn gefunden setzte bzw, gebe der/die Variable U, den wert von NF-2, next springt dann zum nächsten RECORD/nächste Zeile, und suche weiter nach info: und *AA, wobei *AA mir ein ein wenig ungeläufig ist was genau passiert. wildcard ?, wenn das auch wieder gefunden wurde setzte die Varialbe U2 mit dem Wert NF-2, danach vergleichst du die beiden Variable und gibt im Erfolgsfall die Variable U aus....
U="" ..hier setzt du die Variable auf NULL bzw leerst du sie ?!

Danke

Benutzeravatar
heisenberg
Beiträge: 3473
Registriert: 04.06.2015 01:17:27
Lizenz eigener Beiträge: MIT Lizenz

Re: shell script was zwei zeilen parsen tut

Beitrag von heisenberg » 20.12.2016 13:50:56

wobei *AA mir ein wenig ungeläufig ist. wildcard ?
Ja. Diese Art von Wildcard nennt sich Regulärer Ausdruck, auch RegEx genannt - den Begriff hast Du oben ja bereits verwendet. Das ist die verbreitete Methode um Textmuster zu beschreiben.

Siehe z. B. hier: https://danielfett.de/de/tutorials/tuto ... ausdrucke/

Habe jahrelang auch nur awk für machwas | awk '{print $1}' verwendet. Von den Sprachelementen ist awk nicht aussergewöhnlich. Doch es gibt einige Kleinigkeiten, die es erlauben damit extrem kompakten Code zu schreiben.
... unterhält sich hier gelegentlich mangels wunschgemäßer Gesprächspartner mal mit sich selbst.

Benutzeravatar
Meillo
Moderator
Beiträge: 8782
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: shell script was zweil zeilen parsen tut

Beitrag von Meillo » 20.12.2016 15:56:08

ren22 hat geschrieben:wobei *AA mir ein ein wenig ungeläufig ist
Es ist auch nicht *AA sondern .*AA!

Wie heisenberg schon schreibt: Regulaere Ausdruecke!

Siehe auch die Manpages regex(7) und glob(7) -- zweiteres ist das was du kennst; ersteres ist das was du kennenlernen solltest. ;-)

Auf dass es bei dir auch bald heisst: Everybody stand back! https://xkcd.com/208/
Use ed once in a while!

Benutzeravatar
heisenberg
Beiträge: 3473
Registriert: 04.06.2015 01:17:27
Lizenz eigener Beiträge: MIT Lizenz

Re: shell script was zwei zeilen parsen tut

Beitrag von heisenberg » 29.12.2016 19:24:28

Kleiner Nachtrag. Das verschönerte Script war leider funktional nicht mehr korrekt. Deswegen führt dieser Stil wohl nicht zum gewünschten Ergebnis:

Code: Alles auswählen

#!/usr/bin/awk -f

/info:.* A IN$/
  {
  U=$(NF-2)
  next
  }

/info:.*AA IN$/
  {
  U2=$(NF-2)
  if(U==U2) print U
  }

  {
  U=""
  }
In jedem Fall die öffnende geschweifte Klammer in die gleiche Zeile wie den Musterausdruck:

Code: Alles auswählen

#!/usr/bin/awk -f

/info:.* A IN$/  {
  U=$(NF-2)
  next
  }

/info:.*AA IN$/  {
  U2=$(NF-2)
  if(U==U2) print U
  }

  {
  U=""
  }
... unterhält sich hier gelegentlich mangels wunschgemäßer Gesprächspartner mal mit sich selbst.

Antworten