Syntax grep {BLOCK} ARRAY;
oder grep (EXPR, ARRAY); bzw. grep EXPR,ARRAY;
Der Befehl grep ist ein sehr mächtiger und universeller Befehl, mit dem sich bestimmte Einträge in Arrays finden lassen.
Die Ergebnisse werden als neues Array zurückgegeben, bzw. im skalaren Kontext die Anzahl der gefundenen zutreffenden Elemente von des Arrays.
Der grep-Befehl führt die Anweisung(en) in BLOCK oder EXPR für jedes Element des Arrays ARRAY. Dabei kann BLOCK ein oder mehrere Perl-Befehle beinhalten, getrennt durch ein Semikolon, EXPR kann Variablen, Subroutinen-Aufrufe und Befehle enthalten.
Wichtig ist jedoch, daß der grep-Befehl intern für jedes Element von ARRAY das $_ verwendet wird, und jede Änderung an $_ wird automatisch in ARRAY übernommen. Man sollte also Vorsicht walten lassen, da möglicherweise die Originaldaten verändert werden.
grep gibt als Ergebnis eine Liste zurück, die das beinhaltet, was in EXPR oder BLOCK als true, also zutreffend, gefunden wurde.
Sind mehrere Anweisungen in einem BLOCK, so ist die Letzte entscheident, ob ein Element true oder false ist.
Es wird ein Array mit den Elementen 1 - 13 angelegt und per grep werden alle Elemente größer 5 und kleiner 10 ausgegeben.
Ausgabe daher:
6789
Moment mal, könnte man sich jetzt denken, das was der da mit grep macht, das krieg ich auch ganz leicht mit einer foreach-Schleife hin:
@a=(1,2,3,4,5,6,7,8,9,10,11,12,13); foreach (@a){ print $_ if ($_<10 && $_>5);
}
Und was soll ich sagen: o, genau richtig, denn grep macht ja eigentlich auch nichts anderes als jedes Element einzeln zu untersuchen. Abergrep kann vieles wesentlich schneller und vor allem flexibler.
Nächstes Beispiel, mal wieder Dateien finden:
opendir(DIR,"testdir"); my @dateien = readdir(DIR);
closedir(DIR);
Was passiert hier?
Es wird das Verzeichnis testdir geöffnet und eingelesen in ein Array @dateien.
Danach wird per grep ein neues Array erzeugt, in dem alle Dateien enthalten sind, die mit .htm enden. Dieses Array wird schließlich ausgegeben.
Vielleicht nicht so die Killeranwendung im Alltag, jedoch als Beispiel ganz gut, denke ich. Vor allem sieht man, wie einfach und schnell sich die Suche nach der Dateiendung gestaltet und wie übersichtlich der Code ist.
Interessant ist in dem Zusammenhang vielleicht auch die Unterschiedlichkeit der Bedingungen im ersten und im zweiten Beispiel. Während es im ersten Beispiel eine if-Abfrage war, war es hier im zweiten Beispiel eine RegEx. grep ist also sehr vielfältig beim Durchsuchen von Arrays.
Ein Beispiel noch, um den skalaren Kontext etwas besser zu erläutern:
Es wird das Array @a nach Elementen untersucht, die exakt 2 mal auftreten.
Wie geht das?
Das Array @a wird zuerst durch das zweite grep geschleust. Dabei wird der jeweilige Hash-Wert um eins erhöht. Wenn alle Elemente durch sind, übergibt das grep seine Ergebnisse (nämlich alle, bzw. in dem Fall sind es dann die keys des Hashes %temp) dem linken grep, das dann untersucht, welcher Hash-Wert == 2 ist. Diese keys werden dann ausgegeben.
Nächstes Beispiel, eine Datei untersuchen nach dem Vorkommen eines Wortes:
Das Beispiel durchsucht eine Datei nach Zeilen, die die Wörter Sonne oder Sommer enthalten.
Interessant ist in dem Zusammenhang die Tatsache, daß grep das <$IN> ja als Array betrachtet. Dazu wird besagtes <$IN> komplett in den Arbeitsspeicher eingelesen. Na, klingelts? Große Dateien können da schon mal den Rechner lahmlegen! Deswegen sollte dieses Beispiel nur zur Demonstration dienen, im "echten Leben" sollte man lieber die Zeilen einzeln einlesen und durchsuchen! Zum Beispiel so:
open (my $IN,'<datei.txt') || die "Error: $!"; while (<$IN>){ print $_ if ($_=~ /Sommer|Sonne/i);
} close $IN;
Gerade dieses Beispiel zeigt, daß alles, was grep kann, auch mit Schleifen gelöst werden kann.
Aber mit grep ist eben vieles einfacher und meist auch schneller.
Eine etwas ältere, sehr gute Beschreibung von grep, map und sort (leider in Englisch) finden Sie hier.