Siduction Forum

Siduction Forum => Scripting & Kernelhacking => Topic started by: bluelupo on 2018/01/20, 09:58:37

Title: ein kniffliges sed Problem
Post by: bluelupo on 2018/01/20, 09:58:37
Hallo Community,

ich möchte für folgenden grep-Einzeiler ein entsprechendes sed Konstrukt finden um drei Zeilen aus der /var/apt/log/history.log zu extrahieren. Ich suche "Install" am Anfang der Zeile und möchte noch zusätzlich die zwei direkt darüber. Mit egrep funktioniert das soweit.

Code: [Select]
$ egrep -B2 ^'(Install)':.*linux-image-4.8.0-58 /var/log/apt/history.log
Start-Date: 2017-06-29  22:38:33
Commandline: apt-get dist-upgrade
Install: linux-headers-4.8.0-58:amd64 (4.8.0-58.63~16.04.1, automatic), linux-image-4.8.0-58-generic:amd64 (4.8.0-58.63~16.04.1, automatic),.....

Mit sed komme ich nicht weiter. Wie bringe ich den sed dazu mir die zwei Zeilen oberhalb des Treffers auch noch auszugeben (wie beim obigen grep Kommando).

Code: [Select]
$ sed -n '/Install:.*linux-image-4.8.0-58/p' /var/log/apt/history.log
Install: linux-headers-4.8.0-58:amd64 (4.8.0-58.63~16.04.1, automatic), linux-image-4.8.0-58-generic:amd64 ....


EDIT: bin jetzt etwas weitergekommen mit dem sed. Die Zeile vor "Install:" bekomme ich mit folgenden sed Kommando. Jetzt fehlt nur noch die Zeile die mit "Start-Date:" beginnt.

Code: [Select]
$ sed '/^Install:.*linux-image-4.8.0-58/!{h;d};/^Install:.*linux-image-4.8.0-58/{x;G;}' </var/log/apt/history.log
Commandline: apt-get dist-upgrade
Install: linux-headers-4.8.0-58:amd64 (4.8.0-58.63~16.04.1, automatic), linux-image-4.8.0-58-generic:amd64 ....
Title: Re: ein kniffliges sed Problem
Post by: unklarer on 2018/01/20, 14:00:50
Ich kann dir nicht wirklich helfen.   :-\
Vielleicht hilft dir aber dieser Link, (http://www.grymoire.com/Unix/Sed.html) den ich mal abgespeichert hatte...
Title: Re: ein kniffliges sed Problem
Post by: musca on 2018/01/20, 18:09:42
Hallo bluelupo,
sed '/^Start/h;/^Command/H;/^Install/{H;x};/Install/!d' </var/log/apt/history.log

# /^Start/h;   speichert den pattern space im hold space, falls das Pattern mit "Start" beginnt.
# /^Command/H   fügt den pattern space an den hold space an, falls das Pattern mit "Command" beginnt.
# /^Inst/{H;x};   fügt den pattern space an den hold space an und ersetzt den pattern space durch den holdspace, falls das Pattern mit Install" beginnt.
# /Install/!{d}   löscht den pattern space, falls das Pattern nicht "Install" enthält.


cheers
musca
Title: Re: ein kniffliges sed Problem
Post by: Geier0815 on 2018/01/22, 11:51:46
Wenn Du schon weißt das dein erster Treffer "Start-Date:" am Anfang hat und deine Suche mit "Install" beendet wird und Du auch die Zeilen dazwischen brauchst, dann probier mal:
Code: [Select]
sed -n '/^Start-Date:/,/^Install/ p' < /var/log/apt/history.log
Ich weiß aber nicht genau wie gierig der Regex dann ausgewertet wird. Im schlimmsten Fall wird dir alles zwischen dem ersten "Start-Date" und dem letzten "Install" ausgegeben, sieht für mich beim kurzen Testen aber nicht so aus. Schau mal ob's dir taugt.
Ansonsten ist hier der Link zum ausführlichsten sed-Tutorial (http://www.grymoire.com/Unix/Sed.html) das ich kenne.
Title: Re: ein kniffliges sed Problem
Post by: bluelupo on 2018/01/23, 17:14:21
Hi musca,
erstmal Danke für deine Hilfe zum sed. Dein Einzeiler liefert alle Zeilen aus der history.log die am Anfang der Zeile Start|Command|Install stehen haben sowie ich das verstehe. Mich würden aber nur die Zeilen (Start|Command|Install) interessieren wo in der "Install-Zeile" auch das Paket linux-image-* vorkommt. Mit anderen Worten ich möchte den Installationszeitpunkt eines Kernels ermitteln.

Code: [Select]
sed '/^Start/h;/^Command/H;/^Install/{H;x};/Install/!d' </var/log/apt/history.log


EDIT1:
OK, bin schon weitergekommen mit einer bestimmten Kernelversion.

Code: [Select]
$ sed '/^Start/h;/^Command/H;/^Install.*linux-image-4.10.0-27/{H;x};/Install.*linux-image-4.10.0-27/!d' </var/log/apt/history.log

Start-Date: 2017-07-23  16:39:34
Commandline: apt-get dist-upgrade
Install: linux-headers-4.10.0-27-generic:amd64 (4.10.0-27.30~16.04.2, automatic), linux-image-4.10.0-27-generic:amd64 (4.10.0-27.30~16.04.2, automatic), linux-headers-4.10.0-27:amd64 (4.10.0-27.30~16.04.2, automatic), linux-image-extra-4.10.0-27-generic:amd64 (4.10.0-27.30~16.04.2, automatic)

Wenn ich nun noch zum Installationszeitpunkt den Deinstallationszeitpunkt in einem Aufruf bekommen würde wäre dies optimal. Getrennt bekomme ich es schon hin.

Code: [Select]
$ sed '/^Start/h;/^Command/H;/^Purge.*linux-image-4.10.0-27/{H;x};/Purge.*linux-image-4.10.0-27/!d' </var/log/apt/history.log

Start-Date: 2017-09-01  21:44:25
Commandline: apt-get remove --purge --yes linux-headers-4.10.0-27-generic linux-image-4.10.0-27-generic linux-image-extra-4.10.0-27-generic
Purge: linux-headers-4.10.0-27-generic:amd64 (4.10.0-27.30~16.04.2), linux-image-4.10.0-27-generic:amd64 (4.10.0-27.30~16.04.2), linux-image-extra-4.10.0-27-generic:amd64 (4.10.0-27.30~16.04.2)

EDIT2: Geier0815, die sed-Zeile von dir ist ziemlich gierig ;-) Aber trotzdem Danke für den Tipp!
Title: Re: ein kniffliges sed Problem
Post by: Geier0815 on 2018/01/24, 10:35:40
Was Du da bauen willst, ist nicht unbedingt für sed geeignet. Mit "Zeilen vorher" kommt immer das Problem das Du erst einmal jede Zeile im hold-buffer speichern mußt, die nächsten zwei dazu und dann erst dein regex zur Anwendung kommt. Das ist unter sed echt kranke Sch**ße, damit will man nicht arbeiten. Guck dazu mal im von mir und unklarer verlinkten Tutorial unter "Working with multiple lines" nach und da dann ab "Keeping more than one line in the hold buffer".

Für deine erste Beschreibung dessen was Du möchtest, würde ich mit tac (cat nur von der letzten zur ersten Zeile) arbeiten und dann an sed pipe-n. Dann kannst Du mit dem range "/^Install/,/^Start/" arbeiten. Wenn Du dann noch nach "linux-image" suchen willst machst Du aus "/^Install/" eben "/^Install.*linux-image/". Damit solltest Du zumindest die Installations- und Deinstallationszeitpunkte der Kernel finden können.

Aber alles was darüber hinaus in Richtung "Kernel X wurde am bla installiert und am blubb deinstalliert" geht weit über die Möglichkeiten von sed hinaus. Da müßtest Du dann mit awk, perl oder ähnlichem bei gehen weil Du da Variablen mit Kernelversion, installiert oder deinstalliert und Datum versehen mußt die Du vorher durch splitten in den einzelnen Zeilen extrahieren mußt.

Vielleicht solltest Du mal genau beschreiben was Du insgesamt erreichen möchtest und warum. Evtl machst Du dir gerade unnötig Arbeit bzw das Leben schwer