Linux: grep Magie

Geht es Euch auch so auf den Senkel, das, wenn man grep benutzt um in minifizierten Dateien etwas zu suchen, die ganze Datei ausgegeben wird, weil grep als Ergebnis die ganze (eine) Zeile ausgibt?

Ich präsentiere: Das Ende vom Minifizierungsergebnis

Für alle Linux Neulinge, mit grep kann man Dateien, meistens Text, aber nicht notwendigerweise, nach Suchbegriffen durchsuchen. Beispiel:

# grep ErrorLog /etc/httpd/sites/vhosts
ErrorLog logs/error_log
ErrorLog logs/error_log
ErrorLog logs/error_log
ErrorLog logs/error_log
#

Man sieht, das in der Datei vhosts 4x der Begriff ErrorLog in vier verschiedenen Zeilen vorkommt. So weit, so gut.

Was aber, wenn es nur eine einzige Zeile in dem zu durchsuchenden Textblock/Datei gibt?

Damit Ihr das nachvollziehen könnt, hier eine kurze Anweisung:

# wget „https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js“
–2020-04-14 22:57:08– https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
Auflösen des Hostnamens ajax.googleapis.com (ajax.googleapis.com)… 2a00:1450:4007:811::200a, 216.58.204.138
Verbindungsaufbau zu ajax.googleapis.com (ajax.googleapis.com)|2a00:1450:4007:811::200a|:443 … verbunden.
HTTP-Anforderung gesendet, auf Antwort wird gewartet … 200 OK
Länge: nicht spezifiziert [text/javascript]
Wird in »jquery.min.js« gespeichert.

jquery.min.js [ <=> ] 90,92K –.-KB/s in 0,07s

2020-04-14 22:57:08 (1,33 MB/s) – »jquery.min.js« gespeichert [93100]

Das Ergebnis des obigen Befehls ist eine Datei in Eurem Verzeichnis, die „jquery.min.js“ heißt. Schaut Sie Euch mit einem Texteditor an und Ihr werdet sofort verstehen um was es geht.

Suchen wir darin etwas, sagen wir das Wort „function“, was in einer Javascriptdatei häufig vorkommen sollte, erhalten wir lediglich die Zahl „3“ als Ausgabe:

# grep -c function jquery.min.js
3
#

Das liegt daran, daß es in der ganzen Datei nur 3 „Zeilen“ gibt, in denen das Wort vorkommt. Bisschen wenig für JQuery, dem Javascriptframework oder? Schauen wir mal:

# grep function jquery.min.js

Wie man sehen kann, kommt das Wort „function“ da deutlich mehr als dreimal vor und es wird einem praktisch die gesamte Datei ausgegeben, statt nur anzuzeigen, was um den Suchbegriff drumrum ist, wie das bei einer zeilenbasierten Formatierung ( siehe erstes Beispiel ) der Fall wäre. Mit anderen Worten: Je nachdem wie groß die minifizierte Datei ist die man durchsucht, desto mehr völlig unnötigen Zeichensalat bekommt man als Ergebnis, was einem nicht weiterhilft.

Bis jetzt!

Jetzt sagen wir mal grep, daß es nur die Zeichen um das Suchergebnis herum ausgeben soll:

# N=10; grep -roP „.{0,$N}function.{0,$N}“ jquery.min.js
(function(e,t){var
=f.trim,x=function(e,t){retu
-z])/gi,H=function(e,t){retu
Case()},q=function(e){(a.add
ady())},_=function(){a.addEv
or:x,init:function(e,n,r){va
0,toArray:function(){return
his)},get:function(e){return

und siehe da, es werden viel, viele, sehr viele Treffer vom Wort „function“ ausgegeben, jede mit „Kontext“ darum.

Das funktioniert so

„N=10;“ setzt vor dem grep Befehl die Variable N auf 10, was am Ende meint „+- N Zeichen um den Suchbegriff“
„grep -roP“ sucht (-r) rekursiv, (-o) zeige nur den Suchbegriff an und (-P) benutze Reguläre-Suchausdrücke von Perl.
„.{0,$N}function.{0,$N}“  meint jetzt: 0-Nx beliebige Zeichen + „function“ + 0-Nx beliebige Zeichen

Also bekommen wir die obige Ausgabe, weil neben dem was wir suchen vorn und hinten noch maximal 10 beliebige Zeichen zum Suchbegriff zählen. Wer dem jetzt nicht folgen kann, aber interessiert ist, sollte nach „Reguläre Ausdrücke“ googeln und eifrig studieren. Reguläre Ausdrücke, auch Regex genannt, sind eine mächtige Sprache zur Musterformulierung.

Damit können wir jetzt beliebige minifizierte Dateien nach sinnvollem Kram durchsuchen, ohne unsinnig viel Müll zu bekommen.

Cinnamondesktop entfernen, entfernt die falschen Pakete

Vor ein paar Tagen habe ich ja den Cinnamondesktop auf Fedora+Gnome nachinstalliert, und wollte das nun wieder entfernen. Leider entfernt „dnf erase @Cinnamon-Desktop“ einige wichtige Programme, die mit Gnome installiert wurden. Das führt natürlich zu dem Problem, daß man genau diese Pakete wieder installieren muß und dazu eine Liste braucht.

Wie macht man das ?

Abgleichen natürlich. Zunächst brauchen wir die Liste mit den RPMS, die installiert wurden:

grep -i -E „^Jul 01.*fc23“ /var/log/dnf.log-20160704  | grep install | awk ‚{print $7;}‘ | sort >/root/liste.install

Dazu muß man natürlich wissen, wann man Cinnamon installiert hat, in meinem Fall am „Jul 01“ .

Daran denken: An dem Tag können noch andere Pakete installiert worden sein, also ggf. den Grep um die Uhrzeit erweitern!

Jetzt brauchen wir noch die gleiche Liste für die entfernten Pakete:

grep -i -E „^Jul 06.*fc23“ /var/log/dnf.log  | grep erased | awk ‚{print $7;}‘ | sort >/root/liste.erased

Wie bei den Installdaten, könnten auch hier noch andere Pakete deinstalliert worden sein, also auch hier ggf. die Uhrzeit einbauen!

Wer nachvollziehen will, was die einzelnen Befehle machen, kann Sie auch einzeln aufrufen :

grep -i -E „^Jul 06.*fc23“ /var/log/dnf.log  | grep erased | awk ‚{print $7;}‘ | sort
grep -i -E „^Jul 06.*fc23“ /var/log/dnf.log  | grep erased | awk ‚{print $7;}‘
grep -i -E „^Jul 06.*fc23“ /var/log/dnf.log  | grep erased
grep -i -E „^Jul 06.*fc23“ /var/log/dnf.log

Nun hat man zwei Listen mit Paketen. Alle die Pakete, die nicht in der Install-Liste sind, aber in der Erased-Liste, müssen wieder auf den Rechner drauf.

Jetzt könnte es soooo einfach sein :

grep -vf /root/liste.install /root/liste.erased

Ist es aber nicht, denn die Listen passen nicht zusammen. Wir müssen die Paketnamen erst normieren:

sed -e „s/\.x86_64//“ /root/liste.install > /root/liste.install2

sed -e „s/\.fc23.*//“ -e „s/:.*$//“ -e „s/-[0-9].*//“ /root/liste.erased  > /root/liste.erased2

Jetzt können wir Sie vergleichen :

grep -vf /root/liste.install2 /root/liste.erased2

Das zeigt alle Tools an, die in der Install-Liste fehlen, also zuviel deinstalliert wurden.

Das sollte man jetzt von Hand nochmal aussortieren, aber zur Not ginge auch:

grep -vf /root/liste.install2 /root/liste.erased2 | awk ‚{print „dnf -y install „$1;}‘ | bash

und alles würde automatisch installiert werden.

ACHTUNG: Hinweis für spätere Zeiten :

Als dieser Artikel geschrieben wurde, war Fedora 23 aktuell auf einem 64Bit System installiert. Wer andere Versionen einsetzt, muß die ganzen Anweisungen selber sinnvoll anpassen.