Anfang
Inhalt
Einleitung
Erste
Schritte
Die Bash
Das
Dateisystem
Nutzerkommandos
Installation
Shells
Unix-Werkzeuge
Vi
Emacs
Reguläre
Ausdrücke
Grep
Sed
Awk
Make &
Makefile
System-Administration
X Window
System
Der
Kernel
Netzwerk
Grundlagen
Netzwerk
Clients
Netzwerk
Server
Netzwerk
Sicherheit
Anhang
Register
|
Unix Werkzeuge - Grep und verwandte Tools
|
|
»Global search for a regular expression and print out
matched lines« - kurz 'g/re/p' ist das gebräuchlichste Kommando, um in
Dateien nach bestimmten Mustern zu suchen. Die Grep-Familie umfasst die drei Kommandos
egrep, grep und fgrep. Das erste »Extended Grep« (erweitertes grep)
versteht »ein paar mehr« der Regulären Ausdrücke als »grep«. »fgrep« (Fixed
Grep) hingegen unterstützt nur eine eingeschränkte Teilmenge, womit sich die
Suche vor allem in großen Dateien erheblich beschleunigen lässt.
Grep arbeitet bei der Suche wesentlich effizienter als das in einem Editor geschehen
würde. Per Voreinstellung schreibt das Kommando alle Zeilen der Eingabe, die das
gesuchte Muster enthalten, auf die Standardausgabe. Dabei kann die Eingabe beliebig viele
Dateien, als auch die Standardeingabe betreffen. Zudem
liefern die Kommandos der Grep-Familie einen Rückgabewert an das Betriebssystem, was
sie für die Verwendung in Shellprogrammen bevorzugt.
Häufig interessiert man sich nicht für den exakten Inhalt der Zeile, die das
Muster enthält, sondern einzig ob das Muster überhaupt existiert. Vor allem in
Shellskripten wird man die Ausgaben der Kommandos unterdrücken und
anschließend anhand des Rückgabewertes den weiteren Programmablauf
steuern.
Rückgabewert 0 |
|
Muster wurde gefunden:
# "root" sollte es eigentlich in jeder
"passwd" geben
user@sonne> grep root /etc/passwd
>& /dev/null
user@sonne> echo $?
0 |
|
|
Rückgabewert 1 |
|
Muster wurde nicht gefunden:
# "ROOT" gibt es hoffentlich nicht
user@sonne> grep ROOT /etc/passwd
>& /dev/null
user@sonne> echo $?
1 |
|
|
Rückgabewert 2 |
|
Datei nicht gefunden:
# die Datei "/bla" gibt es hoffentlich
nicht
user@sonne> grep text /bla >&
/dev/null
user@sonne> echo $?
2 |
|
Optionen beeinflussen die Arbeitsweise aller Kommandos der Grep-Familie. Welche
Optionen es gibt, beschreibt die folgende Tabelle:
-c |
|
Anzeige der Anzahl Zeilen, in denen das Muster gefunden wurde:
user@sonne> grep -c bash
/etc/passwd
38 |
|
-i |
|
Groß- und Kleinschreibung werden nicht unterschieden:
user@sonne> grep -i ROot
/etc/passwd
root:x:0:0:root:/root:/bin/bash |
|
-l |
|
Nur Anzeige der Namen der Dateien, in denen das Muster gefunden wurde:
user@sonne> grep -l tcp
/etc/host*
/etc/hosts.allow
/etc/hosts.deny |
|
-n |
|
Zeigt die Zeilennummer an, in der das Muster gefunden wurde:
user@sonne> grep -n root
/etc/passwd
1:root:x:0:0:root:/root:/bin/bash |
|
-s |
|
Unterdrückt die Fehlerausgaben (Standardfehler); sinnvoll in
Skripten. |
-v |
|
Zeigt alle Zeilen an, die das Muster nicht enthalten:
# ohne diese Option
user@sonne> ps ax | grep inetd
133 ?
S 0:00 /usr/sbin/inetd
762 pts/2 S 0:00 grep
inetd
# die Ausgabe "grep" herausfiltern
user@sonne> ps ax | grep inetd | grep -v
grep
133 ?
S 0:00 /usr/sbin/inetd |
|
-w |
|
Das Suchmuster muss ein einzelnes Wort sein (also kein Bestandteil eines anderen
Wortes).
user@sonne> echo -e "Automaten\n
essen\n keine Tomaten" | grep -i Tomaten
Automaten
keine Tomaten
user@sonne> echo -e "Automaten\n essen\n
keine Tomaten" | grep -iw Tomaten
keine Tomaten |
|
-A [Anzahl] |
|
Zeigt »Anzahl« Zeilen an, die der Zeile mit dem Muster folgen.
user@sonne> grep -A 2 root
/etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/bash
daemon:x:2:2:daemon:/sbin:/bin/bash
|
|
-B [Anzahl] |
|
Zeigt »Anzahl« Zeilen an, die vor der Zeile mit dem Muster
liegen. |
Nachfolgend sind alle Reguläre Ausdrücke
aufgeführt, die die Kommandos der Grep-Familie unterstützen. Hinter jedem
Muster ist angegeben, welches grep-Kommando diese Syntax beherrscht. Dabei wird nicht
zwischen grep und fgrep unterschieden, da beide Kommandos dieselbe Sprache sprechen (also
grep=fgrep).
^ (grep, egrep) |
|
Beginn der Zeile |
$ (grep, egrep) |
|
Ende der Zeile |
. (grep, egrep) |
|
Genau ein beliebiges Zeichen |
* (grep, egrep) |
|
Beliebig viele des vorangegangenen Zeichens |
[] (grep, egrep) |
|
Ein Zeichen aus dem Bereich. Anstelle von Zeichen können vordefinierte
Klassen von Zeichen verwendet werden: [:alnum:], [:alpha:], [:cntrl:], [:digit:],
[:graph:], [:lower:], [:print:], [:punct:], [:space:], [:upper:], und
[:xdigit:]. |
[^] (grep, egrep) |
|
Kein Zeichen aus dem Bereich |
\< (grep) |
|
Muster am Wortanfang suchen |
\> (grep) |
|
Muster am Wortende suchen |
\(..\) (grep) |
|
Eingeschlossenes Muster vormerken; auf dieses kann später über
\1 zugegriffen werden. Bis zu neun Muster können auf diese Weise
gespeichert werden ( ein Beispiel steht im Abschnitt Reguläre Ausdrücke). |
x\{m\} (grep) |
|
m -faches Auftreten des Zeichens x |
x\{m,n\} (grep) |
|
mindestens m -, maximal n -maliges Auftreten des
Zeichens x |
+ (egrep) |
|
Mindestens ein Auftreten des vorangegangenen Zeichens |
? (egrep) |
|
Höchstens ein Auftreten des vorangegangenen Zeichens |
x|y (egrep) |
|
Zeichen "x" oder Zeichen "y" |
(abc|xyz) (egrep) |
|
Zeichenkette "abc" oder Zeichenkette "xyz". Die runden Klammern können
entfallen. |
Einfache Beispiele zur Anwendung von grep begegneten uns schon an mehreren
Stellen dieses Buches. Nun möchte ich versuchen, anhand typischer Anforderungen bei
der alltäglichen Arbeit mit einem Unix-System, die Verwendung der komplexeren
Mechanismen zu erläutern.
Beispiel 1
Bei der Systemadministration fragt man sich häufig, in welcher Datei
eigentlich welche Shell-Variable gesetzt wird? Die globalen Vorgaben erfolgen zum
Großteil in den Dateien des Verzeichnisses /etc. Also interessieren
uns die Namen der Dateien, in denen z.B. die PATH-Variable modifiziert
wird:
user@sonne> grep -l PATH /etc/*
2>/dev/null
/etc/csh.cshrc
/etc/login.defs
/etc/manpath.config
/etc/profile
/etc/profile.rpmsave
/etc/rc.config
/etc/squid.conf |
Die Umleitung der Fehlerausgabe nach /dev/null ist sinnvoll, da
»grep« nicht auf Verzeichnisse anwendbar ist.
Beispiel 2
Wie viele Nutzer sind Mitglied in der default-Gruppe users (GID
100)?
user@sonne> grep -c
':[0-9]\{1,\}:100:' /etc/passwd
9 |
Bei der Angabe des Suchmusters hilft uns die Kenntnis des Aufbaus der
Datei »/etc/passwd«. Dabei steht die GruppenID immer zwischen zwei
Doppelpunkten. Allerdings könnte es sein, dass auch die NutzerID (UID) 100
vergeben ist - der Ausdruck :[0-9]\{1,\}:100: garantiert, dass
:100: das zweite rein numerische Feld betrifft. Eine andere Schreibweise
ist:
user@sonne> grep -c
':[[:digit:]]\{1,\}:100:' /etc/passwd
9 |
Beispiel 3
Welche Netzwerkdienste über UDP sind auf unserem System verfügbar (Datei
/etc/inetd.conf )?
user@sonne> grep
'^[^#].*[[:space:]]udp' /etc/inetd.conf
time dgram udp
wait root internal
talk dgram udp
wait root /usr/sbin/tcpd in.talkd
ntalk dgram udp
wait root /usr/sbin/tcpd in.talkd
netbios-ns dgram
udp wait root
/usr/sbin/nmbd nmbd |
Jede Zeile, die mit einem # beginnt, ist ein Kommentar. Also
filtern wir solche Zeilen aus (^[^#] ). Das gesuchte Protokoll ist "udp".
Vor diesem Schlüsselwort können beliebig viele Zeichen
(.* ) gefolgt von einem Leerzeichen oder Tabulator
([[:space:]] ) stehen.
Beispiel 4
Je gezielter man nach Informationen fahndet, desto verwirrender wird die Angabe
der Suchmusters. In zahlreichen Fällen wird die Verwendung von Pipes einleuchtender sein. Das Ergebnis aus obigen
Beispiel erhält man auch mit folgender Befehlsfolge:
user@sonne> grep -w udp
/etc/inetd.conf | grep -v ^#
time dgram udp
wait root internal
talk dgram udp
wait root /usr/sbin/tcpd in.talkd
ntalk dgram udp
wait root /usr/sbin/tcpd in.talkd
netbios-ns dgram
udp wait root
/usr/sbin/nmbd nmbd |
Egrep ist hilfreich, wenn Sie nach Zeilen in der Eingabe suchen, die mindestens eine
von mehreren Zeichenketten enthalten.
So findet das folgende Beispiel alle Zeilen der Datei /etc/fstab, in denen »floppy« und
»cdrom« auftauchen:
user@sonne> egrep 'floppy|cdrom'
/etc/fstab
/dev/hdc /cdrom
iso9660 ro,noauto,user,exec 0 0
/dev/fd0 /floppy
auto
noauto,user 0 0
|
Eine weitere interessante Anwendung ist die Suche nach »geteilten« Mustern, d.h. die
bekannten Teile stehen auf einer Zeile, aber der Zwischenraum ist unbekannt. Zur
Demonstration dient folgende Datei:
user@sonne> cat beispiel.txt
1 ein Zwischenraum
2 ein Zwischenraum
3 ein Zwischenraum
4 ein Zwischenraum
|
Gesucht werden sollen alle Zeilen, die »einen Zwischenraum« enthalten; jedoch ist die
Zusammensetzung des Zwischenraums nicht bekannt (und besteht teils aus Leerzeichen, teils
aus Tabulatoren und teils aus beidem). Mit dem normalen grep könnte man sich
mit folgendem Konstrukt behelfen:
user@sonne> grep
"ein[[:space:]][[:space:]]*Zwischenraum" beispiel.txt
1 ein Zwischenraum
2 ein Zwischenraum
3 ein Zwischenraum
4 ein Zwischenraum
|
Die doppelte Anwendung des [:space:]-Musters ist für diesen Fall notwendiger
Ballast, da wir ja mindestens einen Zwischenraum benötigen. Eleganter ist da die
Möglichkeit von "+" in Verbindung mit egrep:
user@sonne> egrep
"ein[[:space:]]+Zwischenraum" beispiel.txt
1 ein Zwischenraum
2 ein Zwischenraum
3 ein Zwischenraum
4 ein Zwischenraum
|
Fgrep kann immer anstelle von grep verwendet werden, falls das zu suchende Muster
keine regulären Ausdrücke enthält. Alle Sonderzeichen in der
Musterzeichenkette verlieren ihre Sonderbedeutung und werden als Bestandteil des Musters
verstanden. Fgrep arbeitet dadurch etwas schneller als grep und ist vor allem beim
Durchsuchen großer Datenmengen nützlich.
|
|