*
hat eine besondere Bedeutung sowohl als Shell- Globbing- Zeichen ("Wildcard") als auch als Metazeichen für reguläre Ausdrücke . Sie müssen beides berücksichtigen. Wenn Sie jedoch Ihren regulären Ausdruck zitieren, können Sie verhindern, dass die Shell ihn speziell behandelt, und sicherstellen, dass er ihn unverändert weitergibt grep
. Obwohl Art ähnlich konzeptionell, welche *
Mittel zur Schale ist ganz anders aus , was es bedeutet , zu grep
.
Zuerst wird die Shell *
als Platzhalter behandelt .
Du sagtest:
Ob der Ausdruck in Anführungszeichen steht, spielt keine Rolle.
Dies hängt davon ab, welche Dateien in dem Verzeichnis vorhanden sind, in dem Sie sich gerade befinden, wenn Sie den Befehl ausführen. Bei Mustern, die das Verzeichnistrennzeichen enthalten /
, kann es davon abhängen, welche Dateien auf Ihrem gesamten System vorhanden sind. Sie sollten immer zitieren reguläre Ausdrücke für grep
--und einfache Anführungszeichen in der Regel Besten-- sind , es sei denn Sie sicher sind , bist du in Ordnung mit den neun Arten von potentiell überraschend Transformationen führt die Shell sonst vor dem Ausführen - grep
Befehl.
Wenn die Shell auf ein *
Zeichen stößt , das nicht in Anführungszeichen steht , bedeutet dies "null oder mehr Zeichen" und ersetzt das Wort, das es enthält, durch eine Liste von Dateinamen, die dem Muster entsprechen. (Dateinamen , die mit beginnen , .
sind ausgeschlossen - es sei denn , Ihr Muster selbst beginnt mit .
oder . Sie haben konfiguriert Shell , sie trotzdem schließen) Dies ist bekannt als Globbing --und auch durch den Namen Dateinamen Expansion und Pfadname Expansion .
Der Effekt mit grep
wird normalerweise sein, dass der erste übereinstimmende Dateiname als regulärer Ausdruck verwendet wird - auch wenn es für einen menschlichen Leser ziemlich offensichtlich ist, dass er nicht als regulärer Ausdruck gemeint ist -, während alle anderen Dateinamen automatisch von Ihrem aufgelistet werden glob werden als Dateien verwendet, in denen nach Übereinstimmungen gesucht werden soll. (Sie sehen die Liste nicht - sie wird undurchsichtig weitergegeben grep
.) Sie möchten praktisch nie, dass dies geschieht.
Der Grund, warum dies manchmal kein Problem ist - und in Ihrem speziellen Fall zumindest bisher nicht - ist, dass *
dies in Ruhe gelassen wird, wenn alle der folgenden Aussagen zutreffen :
Es gab keine Dateien, deren Namen übereinstimmten. ... oder Sie haben das Globbing in Ihrer Shell deaktiviert, normalerweise mit set -f
oder gleichwertig set -o noglob
. Aber das ist ungewöhnlich und Sie würden wahrscheinlich wissen, dass Sie es getan haben.
Sie verwenden eine Shell, deren Standardverhalten darin besteht, sie in *
Ruhe zu lassen , wenn keine übereinstimmenden Dateinamen vorhanden sind. Dies ist in Bash der Fall, das Sie wahrscheinlich verwenden, jedoch nicht in allen Bourne-Shells. (Das Standardverhalten in der beliebten Shell Zsh besteht beispielsweise darin, dass Globs entweder (a) erweitern oder (b) einen Fehler erzeugen.) ... oder Sie haben dieses Verhalten Ihrer Shell geändert - wie dies gemacht wird, ist unterschiedlich über Muscheln.
Sie haben Ihrer Shell nicht anderweitig mitgeteilt, dass Globs durch nichts ersetzt werden sollen, wenn keine übereinstimmenden Dateien vorhanden sind, und dass in dieser Situation keine Fehlermeldung angezeigt wird . In Bash wäre dies durch Aktivieren der Optionnullglob
oder failglob
Shell geschehen .
Sie können sich manchmal auf # 2 und # 3 verlassen, aber Sie können sich selten auf # 1 verlassen. Ein grep
Befehl mit einem nicht zitierten Muster, der jetzt funktioniert, funktioniert möglicherweise nicht mehr, wenn Sie andere Dateien haben oder wenn Sie ihn von einem anderen Ort aus ausführen. Zitieren Sie Ihren regulären Ausdruck und das Problem verschwindet.
Dann wird der grep
Befehl *
als Quantifizierer behandelt .
Die anderen Antworten - wie die von Sergiy Kolodyazhnyy und von kos - sprechen diesen Aspekt dieser Frage ebenfalls auf etwas andere Weise an. Deshalb ermutige ich diejenigen, die sie noch nicht gelesen haben, dies entweder vor oder nach dem Lesen des Restes dieser Antwort zu tun.
Unter der Annahme, *
dass es zu grep kommt - was das Zitieren sicherstellen sollte - bedeutet grep
dies, dass das Element, das davor steht, beliebig oft vorkommen kann , anstatt genau einmal auftreten zu müssen . Es könnte immer noch einmal auftreten. Oder es könnte überhaupt nicht vorhanden sein. Oder es könnte wiederholt werden. Text, der zu einer dieser Möglichkeiten passt, wird abgeglichen.
Was meine ich mit "Artikel"?
Ein einzelnes Zeichen . Da b
Findet ein Zeichen b
, b*
entspricht null oder mehr b
s, also ab*c
passt ac
, abc
, abbc
, abbbc
etc.
Da in ähnlicher Weise .
jedes Zeichen , .*
entspricht null oder mehr Zeichen 1 , so a.*c
Streichhölzer ac
, akc
, ahjglhdfjkdlgjdfkshlgc
, selbst acccccchjckhcc
, usw. Oder
Eine Charakterklasse . Da [xy]
Streichhölzer x
oder y
, [xy]*
entspricht null oder mehr Zeichen , wo jeder entweder ist x
oder y
damit p[xy]*q
übereinstimmt pq
, pxq
, pyq
, pxxq
, pxyq
, pyxq
, pyyq
, pxxxq
, pxxyq
, usw.
Dies gilt auch für Formen Kurzschrift von Zeichenklassen wie \w
, \W
, \s
, und \S
. Da \w
mit jedem Wortzeichen \w*
übereinstimmt , entspricht es null oder mehr Wortzeichen. Oder
Eine Gruppe . Da \(bar\)
Streichhölzer bar
, \(bar\)*
Streichhölzer null oder mehr bar
s, also foo\(bar\)*baz
passt foobaz
, foobarbaz
, foobarbarbaz
, foobarbarbarbaz
etc.
Behandelt Ihren regulären Ausdruck mit den Optionen -E
oder als ERE bzw. PCRE und nicht als BRE , und dann werden Gruppen von anstelle von umgeben , sodass Sie stattdessen anstelle von und anstelle von verwenden .-P
grep
(
)
\(
\)
(bar)
\(bar\)
foo(bar)baz
foo\(bar\)baz
man grep
bietet am Ende eine einigermaßen leicht zugängliche Erklärung der BRE- und ERE-Syntax sowie eine Auflistung aller grep
am Anfang akzeptierten Befehlszeilenoptionen . Ich empfehle diese Handbuchseite als Ressource sowie die GNU Grep-Dokumentation und diese Tutorial- / Referenzseite (auf die ich oben mit einer Reihe von Seiten verlinkt habe).
Zum Testen und Lernen grep
empfehle ich, es mit einem Muster, aber ohne Dateinamen aufzurufen. Dann nimmt es Eingaben von Ihrem Terminal entgegen. Zeilen eingeben; Die Zeilen, die an Sie zurückgesendet werden, enthalten Text, mit dem Ihr Muster übereinstimmt. Drücken Sie zum Beenden Ctrl+ Dam Anfang einer Zeile, die das Ende der Eingabe signalisiert. (Oder Sie können wie bei den meisten Befehlszeilenprogrammen Ctrl+ drücken C.) Zum Beispiel:
grep 'This.*String'
Wenn Sie das --color
Flag verwenden, grep
werden die spezifischen Teile Ihrer Zeilen hervorgehoben, die Ihrem regulären Ausdruck entsprechen. Dies ist sehr nützlich, um herauszufinden, was ein regulärer Ausdruck bewirkt, und um zu finden, wonach Sie suchen, sobald Sie dies tun. Standardmäßig verfügen Ubuntu-Benutzer über einen Bash-Alias, der grep --color=auto
zur Ausführung führt - was für diesen Zweck ausreichend ist -, wenn Sie grep
über die Befehlszeile ausgeführt werden, sodass Sie wahrscheinlich nicht einmal --color
manuell übergeben müssen.
1 Daher bedeutet .*
in einem regulären Ausdruck, was *
in einem Shell-Glob bedeutet. Der Unterschied besteht jedoch darin, dass grep
automatisch Zeilen gedruckt werden, die Ihre Übereinstimmung an einer beliebigen Stelle enthalten. Daher ist es normalerweise nicht erforderlich, sie .*
am Anfang oder Ende eines regulären Ausdrucks zu haben.
* != any number of unknown characters
Lesen Sie das Dokument.)