Beschreibung
von Textmustern
- Die Elemente eines regulären
Ausdrucks
Man kann sich schrittweise an die
Elemente eines solchen Ausdrucks herantasten. Im einzelnen wird kurz vorgestellt:
1. Das boolsche UND
Beispiel: (wort1 UND wort2) werden in
allen .doc Dateien gesucht.
Lösung:
grep -E 'wort1.*wort2|wort2.*wort1'
*.doc
< (wort1 UND wort2) entspricht (wort2 UND wort1) >
Oder auch (vgl. oben)
grep -il wort1 *.doc | xargs grep
-il wort2
2.
Das boolsche ODER
Beispiel: (wort1 ODER wort2) werden in
allen *.doc Dateien gesucht.
Lösung:
grep -E 'wort1|wort2' *.doc
< Die pipe '|'
ist von sich aus kommutativ, sie bringt quasi ein ODER bereits mit>
3.
Das boolsche UND NICHT
Beispiel: Gesucht wird (wort1 UND NICHT
wort2) in allen Dateien vom Typ ".doc"
<umzuformen in (NICHT wort2 UND wort1)>
Lösung:
grep -v wort2 *.doc | grep wort1
< -v gibt nur
die Dateien aus, die das ausgeschlossene wort2 nicht enthalten, die Suche
wird quasi invertiert. Die Ausgabe wird dann nach wort1 durchsucht>
4.
Einfache Kombination von UND und UND NICHT
Das Beispiel: ((wort1 UND
wort2) UND NICHT wort3)
entspricht
((NICHT wort3) UND wort1 UND wort2)
Der Befehl muss lauten:
grep -v wort3 datei.txt | grep -E
'wort1.*wort2|wort2.*wort1'
< Hier wird zunächst wieder mit -v wort3 ausgeschlossen,
dann erfolgt eine Suche wie in Szenario 3.>
5.
Das boolsche NAHE BEI - der Stellungsoperator NEAR
5.1
Notwendige Vorarbeit - die Lösung des Zeilenproblems
Zeichenbstände - Praktikabel?
Einzelne Zeichenabstände lassen sich
genau durch Punkte definieren, da sie abgesehen vom Leerzeichen beliebige
Symbole repräsentieren.
Beispiel:
"Donaudampfschiffskapitän"
wird gefunden durch Suche nach
"Donau.....schiffskapitän"
Das ist auf Wortebene aber nicht praktikabel.
Worte sind durch Leerzeichen getrennt. Diese lassen sich durch Punkte aber
nicht darstellen. Auf Zeilenumbrüche ist man bei der Suche nicht angewiesen.
Damit ergibt sich ein anderer praktikabler Ansatz um der NEAR-Option nahezukommen,
und ein auch ein weiteres Problem.
Zunächst stellt sich das Problem,
dass Zeilen die kleinsten Suchelemente für grep
sind. Will man über den gesamten Text nach Abständen suchen,
so muss man die Zeilumbrüche entfernen.
Wie lassen sich Zeilenumbrüche
entfernen?
Hierzu kann folgendes Kommando verwendet
werden:
tr -d \\012 < beispieldatei.txt
<hierbei steht tr
für translate und -d
für delete, \\012 ist
das ASCII-Symbol für den Zeilenumbruch und das '<'
hat die Funktion, klarzustellen, in welcher Datei die Zeilenumbrüche
entfernt werden sollen.>
5.2
Anwendung des Kommandos zur Zeilenumbruchentfernung
Das in "datei.txt" zu Suchende Beispielmuster
sei "(wort1 UND wort2)"
Versagt aufgrund eines Zeilenumbruchs die
Suche mit diesem Befehl:
grep -E 'wort1.*wort2|wort2.*wort1'
datei.txt
könnte dieser Suchbefehl zu Ergebnissen
führen:
cat datei.txt | tr -d \\012 | grep
-E 'wort1.*wort2|wort2.*wort1'
< 'cat' entspricht
ungefähr dem Kommando 'type'
unter DOS, es gibt den Inhalt einer Datei zeilenweise auf der Konsole aus,
das ist bei großen Dateien unbefriedigend. Daher gibt es 'cat',
'more'
und 'less',
sie bilden eine
Trias. ´'more'
und 'less' zeigen Dateiinhalte
seitenweise an - eine sinnvolle Ergänzung zu 'cat'.
Funktion:
-
cat dateiname zeigt die Datei
an
-
cat dateiname | more zeigt die
Datei seitenweise an und erlaubt Blättern vorwärts mit den Tasten
Return
und Space, beenden mit 'q'.
-
less dateiname zeigt zeigt die
Datei seitenweise an und erlaubt Blättern in beide Richtungen mit
BILD, beenden mit 'q'; less
benötigt aber eine optimal eingestellte Konsole. >
Da häufig alle Dateien des Verzeichnisses
durchsucht werden sollen bietet sich für das Beispielmuster (wort1
UND wort2) folgendes an:
u = dateiname.dateityp
for u in 'ls':
do
echo $u:;
cat $u |tr -d \\012|grep - E 'wort1.*wort2|wort2.*wort1';
done | tee ergebnis.txt
<Ziel ist die gleichzeitige Ausgabe auf dem
Bildschirm und das Speichern des Ergebnisses in einer Datei. Deshalb wird
das Kommando tee verwendet.
Es veranlaßt den Rechner zur Erfüllung dieser Aufgabe.>
5.3 Beispiele für die Stellungsoperatoren
NAHE BEI und GEFOLGT VON
5.3.1
Beispiel für den Stellungsoperator NAHE BEI
Das folgende Beispiel ist für die
Suche des Musters (wort1 NAHE BEI wort2) mit maximal 2 Worten Abstand innerhalb
datei.txt ausformuliert:
grep (wort1 ([^ ]* ) {0,2}wort2|wort2
([^ ]* ) {0,2}wort1) datei.txt
< ^ verneint Leerzeichen
; * erlaubt n Vorkommen
>
5.3.2
Verfeinerung des Operators NAHE BEI zu GEFOLGT VON
Ist es nicht egal in welcher Reihenfolge
die Worte auftauchen, darf natürlich der Befehl nicht wie im obigen
Beispiel 5.3.1 kommutativ sein. Vielmehr muss das wort1, dass in einem
bestimmten Abstand von einem wort2 gefolgt werden soll auch in der Suche
vorne stehen.
Man kann bei der Suche in datei.txt statt
den Operator NAHE BEI den Operator GEFOLGT VON verwenden.
Wird das Muster (wort1 GEFOLGT VON wort2)
gesucht, wobei maximal 2 Worten Abstand zwischen den Worten sein soll,
muss der Suchbefehl lauten:
grep (wort1 ([^ ]* ) {0,2}wort2 datei.txt
< ^ verneint Leerzeichen
; * erlaubt n Vorkommen
>
6. Ergebnis
Man kann mit grep
eine ganze Menge machen, auch komplexe Suchanfragen lassen sich realisieren.
Für diese wäre aber ein grafisches Frontend, welches zumindest
die hier vorgestellten Operatoren umsetzt, eine wesentliche Erleichterung.
Leider bin ich nicht in der Lage ein solches Projekt in Angriff zu nehmen.
Im Hausgebrauch (1 user, 1 Rechner, Daten
auf HD) ist grep auch bei größeren Datenmengen und komplexen
Suchmustern sicher performant genug. Ob das in einem größeren
Umfang (viele user greifen über LAN zu, Daten auf HD oder CD-ROM des
servers) immer noch der Fall wäre entzieht sich aber meiner
Kenntnis.
Bitte senden
Sie mir Ihre Anmerkungen und Verbesserungsvorschläge.
Danke:
Ohne die engagierte Mithilfe von Andreas
Sigg würde es diese Seite so nicht geben, er hat wesentlich dazu beigetragen.
Herzlichen Dank!
zum Inhalt
|