Am Mittwoch, 30. April 2003 06:49 schrieb Bernd Brodesser:
Was macht dieser Befehl? Lenken wir mal die Aufmerksamkeit auf den letzten Teil: grep lib* Als erstes wird dies von der bash interpretiert. Falls es im aktuellen Verzeichnis eine Datei gibt, die mit lib anfängt, so wird lib* durch diesen Namen ersetzt, und es wird nicht mehr nach lib* gesucht, sondern nach libanon, oder wie immer diese Datei heißt. Gibt es gar mehere Dateien, die mit lib anfangen, so wird lib* durch all diese Namen ersetzt und es grep so übergeben. Dann aber interpretiert grep nur das erste Wort als Suchwort, und alle anderen als Dateien in denen gesucht werden soll, aus der Pipe wird dann nicht mehr gelesen. (bash-newbie ist wohl kein Bestandteil Deines Befehls) Es hängt somit im Hohen Maße von dem aktuellen Verzeichnis ab. Nur wenn keine Datei mit lib anfängt bekommt grep das lib* überhaupt zu sehen. Das ist doch sicherlich nicht so gewollt.
Um dieses Verhalten zu vermeiden muß Du den * vor der bash schützen. Entweder indem Du ein \ vor dem * setzt oder aber lib* in " bzw ' setzt.
Aber dann übergibst Du grep lib*. grep kennt aber keine shell-Wildcards, sondren RegExp. Die funktionieren ganz anders. lib* steht für ein l gefolgt von genau ein i gefolgt von beliebig viele, auch kein, b irgendwo in einer Zeile. Zeilen, die diese Bedingung erfüllen, werden ausgegeben. Das mit dem b* kannst Du Dir genausogut sparen. lib* macht nichts anderes als li denn b* umfaßt auch kein b und insgesamt reicht es, wenn der Suchbegriff sich irgendwo in der Zeile befindet, daß muß nicht am Anfang oder Ende sein, kann auch mitten drin sein. Es wird somit jede Zeile ausgegeben, die irgendwo li enthält. Was Du willst ist grep "^lib" Dabei steht das ^ für den Zeilenanfang. ^lib bedeutet somit, daß lib am Zeilenanfang stehen muß.
RegExp werden unter anderem von grep, aber auch von vielen anderen Programmen benutzt. Siehe auch man regex
RegExp sind sehr, sehr mächtig und es lohnt sich, sich ein wenig damit zu befassen.
Aber die bash benutzt sie nicht. Die bash benutzt Wildcards. Insgesamt ist Dein Problem weniger ein bash-Problem als ein grep und RegExp Problem.
Von der bash solltest Du aber wissen, daß sie die Ersetzungen vornimmt.
Angenommen im aktuellen Verzeichnis gibt es folgende Dateien:
$ ls
bar baz foo foobar foobaz
und Du machst jetzt ein
$ cmd foo*
so ersetzt die bash foo* durch foo foobar foobaz, das aufgerufene Programm bekommt folgendes Argumente zu sehen:
ARG 0: cmd ARG 1: foo ARG 2: foobar ARG 3: foobaz
Als 0. Argument wird immer der Dateiname selber übergeben, aber das ist hier nicht wichtig. Wichtig sind die folgende Argumente. Das aufrufende Programm sieht nicht, daß der Anwender ursprünglich foo* und nicht foo foobar foobaz gesagt hat. Mithin reagiert der Befehl exakt so, als hätte der Anwender von vorneherein
$ cmd foo foobar foobaz
gesagt, das Programm hat keinerlei Möglichkeiten es zu unterscheiden. Natürlich nur solange sich im aktuellen Verzeichnis genau die Dateien foo foobar und foobaz befinden, die mit foo beginnen. Das $ oben soll übrigens der Prompt sein.
Danke für die mächtige Anwort. Bei erster Lektüre habe ich immerhin mitbekommen, daß die bash und einige Standardbefehle so mächtig sind, daß ich erst (noch) ein paar Stunden lesen sollte, bevor ich auf gut Glück anfange herumzuhantieren. Das mit den RegExp war mir völlig neu. Peter