Welcome, Guest. Please login or register.
Did you miss your activation email?

Author Topic: [DE] ein kniffliges sed Problem  (Read 10684 times)

Offline bluelupo

  • User
  • Posts: 2.068
    • BluelupoMe
[DE] ein kniffliges sed Problem
« 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 ....
« Last Edit: 2018/01/20, 12:47:50 by bluelupo »

Offline unklarer

  • User
  • Posts: 886
Re: ein kniffliges sed Problem
« Reply #1 on: 2018/01/20, 14:00:50 »
Ich kann dir nicht wirklich helfen.   :-\
Vielleicht hilft dir aber dieser Link, den ich mal abgespeichert hatte...

Offline musca

  • User
  • Posts: 725
  • sid, fly high!
Re: ein kniffliges sed Problem
« Reply #2 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
„Es irrt der Mensch, solang er strebt.“  (Goethe, Faust)

Offline Geier0815

  • User
  • Posts: 599
Re: ein kniffliges sed Problem
« Reply #3 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 das ich kenne.
Wenn Windows die Lösung ist...
kann ich dann bitte das Problem zurück haben?

Offline bluelupo

  • User
  • Posts: 2.068
    • BluelupoMe
Re: ein kniffliges sed Problem
« Reply #4 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!
« Last Edit: 2018/01/23, 18:37:13 by bluelupo »

Offline Geier0815

  • User
  • Posts: 599
Re: ein kniffliges sed Problem
« Reply #5 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
« Last Edit: 2018/01/24, 10:41:33 by Geier0815 »
Wenn Windows die Lösung ist...
kann ich dann bitte das Problem zurück haben?