grep output zeilenweise vergleichen (= oder =!)

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
michaa7
Beiträge: 4628
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

grep output zeilenweise vergleichen (= oder =!)

Beitrag von michaa7 » 06.02.2014 20:50:29

Der ouput von grep sei:
x
y

und ich möchte wissen ob x=y oder x!=y (ob die zeileninhalte gleich oder verschieden ist). Der output besteht immer nur aus zwei zeilen. Es geht dabei darum zwei versionsangaben ala ddd.ddd.dd.dd als gleich oder ungleich zu erkennen.

Und meine nächste frage wäre:
Wenn gleich soll nichts passieren, wenn ungleich -> mail an root. Wie nähere ich mich dieser lösung.

Das ganze ist teil eines scriptes.

Was tun sprach michaa7?
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: grep output zeilenweise vergleichen (= oder =!)

Beitrag von Cae » 06.02.2014 20:54:42

Zum Beispiel per Shell:

Code: Alles auswählen

#!/bin/sh

grep ... | {
	read foo
	read bar

	if [ "x$foo" = "x$bar" ]; then
		# Zeilen gleich
	fi
}
Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

michaa7
Beiträge: 4628
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

Re: grep output zeilenweise vergleichen (= oder =!)

Beitrag von michaa7 » 06.02.2014 21:28:52

Cae hat geschrieben:Zum Beispiel per Shell:

Code: Alles auswählen

#!/bin/sh

grep ... | {
	read foo
	read bar

	if [ "x$foo" = "x$bar" ]; then
		# Zeilen gleich
	fi
}
Gruss Cae
Ich verstehe hier nicht wie "foo" und "bar" in das script gelangen? Das soll doch meinem grep-output "x" und "y" entsprechen. Ich habe also im VT (und nicht in einer datei) den output
x
y
gefiltert in meinen script durch dieses konstrukt:
update-flashplugin-nonfree --status | grep -o ": [[:digit:]]*.[[:digit:]]*.[[:digit:]]*.[[:digit:]]*"

Wie also gelangt mein output in dein script? Leider finde ich weder "man read" noch etwas passendes in "man bash". Wo muß ich schauen?
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

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

Re: grep output zeilenweise vergleichen (= oder =!)

Beitrag von uname » 06.02.2014 21:49:15

Das Script habe ich nicht verstanden. foo und bar sind normalerweise Platzhalter.

Hier mal als awk, kann man bestimmt noch verbessern. Den nächsten Schritt erst wenn das ungefähr deinen Ansprüchen entspricht. Dein Zeug vor dem Pipe einfügen.

Code: Alles auswählen

|awk '{a[NR] = $0} END{if (a[1] == a[2]) {print "gleich"} else {print "ungleich"}}'

Benutzeravatar
4A4B
Beiträge: 926
Registriert: 09.11.2011 11:19:55
Kontaktdaten:

Re: grep output zeilenweise vergleichen (= oder =!)

Beitrag von 4A4B » 06.02.2014 22:04:29

michaa7 hat geschrieben:Ich verstehe hier nicht wie "foo" und "bar" in das script gelangen?
Das erste read liest die erste Zeile des Outpus von grep ('x') in die Variable foo, das zweite read liest die zweite Zeile des Outpus von grep ('y') in die Variable bar. Weiter unten wird dann der Inhalt von $foo mit dem von $bar verglichen
Leider finde ich weder "man read" noch etwas passendes in "man bash".
Für Shell-Builtins eignet sich help zum Nachlesen, also "help read"

michaa7
Beiträge: 4628
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

Re: grep output zeilenweise vergleichen (= oder =!)

Beitrag von michaa7 » 06.02.2014 22:56:47

Ok, danke euch beiden für die hilfe soweit (noch nicht fertig! ;-) )

Ich habe das jetzt sowohl mit der awk- als auch mit der script-foo-bar lösung hinbekommen und es tut was es soll (wobei mit dem script zunächst ein fehler auftrat (fi unexpected..), was wohl daran lag dass nach "then" irgendetwas anderes als ein kommentar folgen muß. 'echo "Zeilen gleich"' behob den fehler, und soweit funktioniert das. Ich habe das mit der awklösung auch leicht abgewandelt mit nichtgleichen zahlen getestet und auch das funktioniert.

Danke auch für die erklärung wie read foo zu verstehen ist und und wie ich zu hilfe dafür komme.

Nun muß ich noch den letzten schritt gehen und im fehlerfall eine mail an root schicken. Ich würde gerne mit der script variante weitermachen weil sie mir durchsichtiger ist. Ich muß nun also noch erreichen, dass bei ungleichheit eine mail an root mit inhalt "tuwas" geht.

vermutlich also ein

Code: Alles auswählen

else
<wie veranlasse ich eine mail an rot mit inhalt "tuwas">
fi


Noch ein hinweis: das fertige script läuft als täglicher cronjob. Ich erwähne das, weil ich nicht weiß ob man dafür mit 'then echo "Zeilen gleich"' vielleicht anders umgehen muß, weil es ja dann kein VT gibt in dem echo etwas anzeigen könnte. Ich muß und will das ja gar nicht sehen, es soll aber auch nicht zu einem ausführungsfehler führen. Zu testzwecken ist da natürlich gut und sogar notwendig, damit ich sehe was passiert.

vielleicht so?

...
else
mail -s "tuwas" root <<EOM
Hallo Admin,
tuwas
Mit freundlichem Gruss updatescript
EOM
ergoogelt mit fragezeichen was *genau* "<<" und "EOM" (end of message) hier tun. Und apt-cache policy mail sagt mir dass "mail" *nicht* installiert ist, und ich wohl besser die vorhandene (muß ich noch finden) CL mailanwendung nutze. Irgendwas muß ja schon dasein weil cron mir regelmäßig benachrichtigungen schickt.
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

Benutzeravatar
4A4B
Beiträge: 926
Registriert: 09.11.2011 11:19:55
Kontaktdaten:

Re: grep output zeilenweise vergleichen (= oder =!)

Beitrag von 4A4B » 07.02.2014 00:02:42

Ich erwähne das, weil ich nicht weiß ob man dafür mit 'then echo "Zeilen gleich"' vielleicht anders umgehen muß, weil es ja dann kein VT gibt in dem echo etwas anzeigen könnte.
Du kannst auch einfach ein ":" reinsetzen, das bedeutet "tue nichts"

Code: Alles auswählen

   if [ "x$foo" = "x$bar" ]; then
      :
   fi
... andernfalls sendet dir cron die Ausgaben von echo per mail zu :)
mit fragezeichen was *genau* "<<" und "EOM" (end of message) hier tun
Das ist ein sogenanntes Heredoc, was u.a. hier beschrieben ist:

http://tldp.org/LDP/abs/html/here-docs.html
Und apt-cache policy mail sagt mir dass "mail" *nicht* installiert ist
Der Befehl mail ist in dem Paket Debianbsd-mailx enhalten, welches standardmäßig in Debian installiert ist.

Bei einem Cronjob würde ich zur Sicherheit noch die absoluten Pfade angeben, also z.B. /bin/grep, /usr/bin/mail

michaa7
Beiträge: 4628
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

Re: grep output zeilenweise vergleichen (= oder =!)

Beitrag von michaa7 » 07.02.2014 01:55:10

Danke euch beiden, script ist fertig.

Zum schluß aber noch drei rückfragen, zu dingen die mir bei der scripterstellung aufgefalen sind:

1)
Eine mit "awk" beginnende zeile ließ sich nicht wirksam auskommentieren. Trotz kommentarzeichen "#" am zeilenanfang wurde die zeile interpretiert, jedoch mit fehlermeldung.
???
Ahh, das wird wohl an [3)] gelegen haben. Das geht so einfach gar nicht.

2)
Gibt es irgendeine möglichkeit in einem shellscript code temporär über mehrere zeilen auszukommentieren, und zwar anders als über das umständliche setzen eines "#" an *jeden* einzelnen zeilenanfang?

3)
An welchen stellen im script darf ich nicht komentieren? Im hier oben verlinkten script scheint es au?er nach dem shebang keine möglichkeit für einen kommentar zu geben, dass alles jeweils über pipes weitergeleitet wird, und zwische if und fi darf wohl auch kein kommentar stehen. Welche unterbrechungen im script gibt es denn die überhaupt eine kommentarzeile erlauben? Kommentare am zeilenende sind offenbar auch nicht möglich.
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: grep output zeilenweise vergleichen (= oder =!)

Beitrag von Cae » 07.02.2014 05:02:06

michaa7 hat geschrieben:2)
Gibt es irgendeine möglichkeit in einem shellscript code temporär über mehrere zeilen auszukommentieren, und zwar anders als über das umständliche setzen eines "#" an *jeden* einzelnen zeilenanfang?
Man kann einen gescheiten Editor hernehmen, der einem die Rauten als Block setzen kann... ansonsten sind logische Konstrukte wie

Code: Alles auswählen

false && {
	echo dummy
}
# bzw. kuerzer
: || {
	echo dummy
}
an vielen Stellen moeglich (: ist true). Beide Bedingungen sind niemals wahr, weshalb der Anweisungsblock nie ausgefuehrt wird, genau wie ein Kommentar. Bei Pipes geht das aber haeufig nicht, da muss man meist den kompletten Block wegschieben bzw. auf Kommentare verzichten. Allerdings kann man zum Beispiel in den per Kommandozeile uebergebenen awk-Code selbst Kommentare einfuegen:

Code: Alles auswählen

$ date \
> | cat \
> | awk '{print} # emuliert cat(1)' \
> | more
Fri Feb  7 04:56:36 CET 2014
$ 
Zwischen diese sinnlos-Pipes koennte man normalerweise keinen Kommentar packen. Auch koennte man die Pipes zwischen Shell-Funktionen aufspannen, in denen man wiederum lustig herumkommentieren kann.

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

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

Re: grep output zeilenweise vergleichen (= oder =!)

Beitrag von Meillo » 07.02.2014 09:29:16

michaa7 hat geschrieben:Der ouput von grep sei:
x
y

und ich möchte wissen ob x=y oder x!=y (ob die zeileninhalte gleich oder verschieden ist). Der output besteht immer nur aus zwei zeilen. Es geht dabei darum zwei versionsangaben ala ddd.ddd.dd.dd als gleich oder ungleich zu erkennen.

Und meine nächste frage wäre:
Wenn gleich soll nichts passieren, wenn ungleich -> mail an root. Wie nähere ich mich dieser lösung.
Ein alternativer Ansatz:

Code: Alles auswählen

if expr `grep ... | uniq | wc -l` = 1 ; then
	exit
fi
mail root <<!
Die Zeilen sind verschieden.
!
Use ed once in a while!

Antworten