Ich suche nach einer Klassendeklaration auf einer Site mit Hunderten von PHP-Dateien. Wie kann ich dies im aktuellen Ordner und in den Unterordnern mit grep tun ?
Ich cd
habe den Ordner getestet und dann so etwas
grep -r 'class MyClass' *.php
Ich suche nach einer Klassendeklaration auf einer Site mit Hunderten von PHP-Dateien. Wie kann ich dies im aktuellen Ordner und in den Unterordnern mit grep tun ?
Ich cd
habe den Ordner getestet und dann so etwas
grep -r 'class MyClass' *.php
Antworten:
Ich würde empfehlen, dass Sie so etwas wie ctags verwenden, anstatt es mit einem grep zu tun. Wenn Sie möchten, können Sie jedoch so etwas tun
find <top level dir> -name \*.php | xargs grep "class MyClass"
Dies setzt natürlich voraus, dass Sie nur einen einzigen Abstand zwischen class
und myClass
möglicherweise nicht wahr haben. Es ist jedoch einfach, den regulären Ausdruck zu ändern, um nach einer beliebigen Anzahl von Leerzeichen zu suchen.
Wenn Sie verwenden -r
, möchten Sie wahrscheinlich nur das aktuelle Verzeichnis rekursiv durchsuchen :
grep -r 'class MyClass' .
Beachten Sie den Punkt am Ende des oben genannten.
Was Sie gesagt haben, grep
war, dass Sie wollten, dass jede *.php
Datei oder jedes Verzeichnis rekursiv durchsucht wird , aber Sie hatten wahrscheinlich keine Verzeichnisse, die mit der Erweiterung .php endeten. Das Obige ist die einfachste Möglichkeit, die Suche durchzuführen, enthält jedoch auch Dateien anderer Typen, was besonders problematisch ist, wenn Sie überall .svn-Verzeichnisse haben. Wenn Sie nicht viele andere Dateitypen haben, ist das oben Genannte im Allgemeinen ausreichend und funktioniert gut.
Die meisten Inkarnationen von grep haben keine Möglichkeit, Dateierweiterungen anzugeben, die durchsucht werden können. Daher verwenden Sie find im Allgemeinen in Verbindung damit:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;
-iname
teilt einigen Versionen von grep mit, dass Sie eine Dateinamensuche ohne Berücksichtigung der Groß- und Kleinschreibung durchführen möchten, aber viele der Nicht-GNU-Varianten von find unterstützen dies nicht, sodass Sie sie -name
stattdessen verwenden können.
Die -exec
obige Option hat den Nebeneffekt, dass für jede Datei grep aufgerufen wird, was ziemlich kostspielig ist.
Wieder andere Versionen von grep unterstützen a, mit +
dem find angewiesen wird, die Argumente zusammenzufügen, um die Anzahl der Aufrufe der ausführbaren Datei zu verringern:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;
Ein häufig empfohlener Weg, um Aufrufe zu reduzieren, ist die Verwendung von xargs, die grep so oft wie möglich, aber so oft wie nötig auslösen:
find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"
xargs
ist klug genug, um grep bis zur maximalen Anzahl von Argumenten zu übergeben, die in der Befehlszeile unterstützt werden, aber die obige Variante behandelt bestimmte Zeichen wie Leerzeichen nicht sehr gut. Wäre beispielsweise 'the file.php', würde ein Dateiname grep 'the' als Argument und 'file.php' als Argument erhalten, sodass beide nicht gefunden würden. Stattdessen verwenden wir:
find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"
print0
und -0
arbeiten Sie zusammen und verwenden Sie Argumente, denen ein Nullzeichen folgt, damit das Argument vollständig und eindeutig identifiziert wird.
Wenn Sie jemals mehr als ein Leerzeichen class
oder eine Registerkarte haben, möchten Sie möglicherweise mehr Zeichen zulassen, indem Sie den regulären Ausdruck ändern:class[ \t]*MyClass
Dieser Beitrag zu StackOverflow enthält weitere Beispiele und zeigt, wie bestimmte Verzeichnisse wie .svn-Verzeichnisse ausgeschlossen werden.
grep -r 'class MyClass' *.php
durchsucht alle Ordner mit Namen, die mit .php enden
grep -r 'class MyClass' . | grep .php
sucht in allen Dateien in allen Unterordnern nach der Klasse MyClass und gibt dann nur diejenigen zurück, die .php enthalten.
find . -type f -name *.php -print -exec grep \"class MyClass\" {} \;
Sie erhalten den Inhalt der Zeile sowie den Pfad zur Datei.
Möglicherweise möchten Sie die Groß- und Kleinschreibung nicht berücksichtigen und Leerzeichen tolerieren. Grep wird beendet, wenn im aktuellen Verzeichnis keine Instanzen des gewünschten Dateimusters gefunden werden. Es muss sozusagen wissen, wo es anfangen soll, und keine übereinstimmenden Dateien erzeugen keinen Startpfad.
Wenn mindestens eine Datei mit der gewünschten Erweiterung vorhanden ist, können Sie egrep -ir verwenden. find
und xargs
zeigen Sie ihre Leistungsfähigkeit mit einzelnen flachen (aber sehr großen) Verzeichnissen, in denen grep fehlschlägt, und zusätzlichen Qualifikationsmerkmalen (zum Beispiel, wenn Sie nur nach .inc-, .php- und php3-Dateien suchen möchten). Aber meiner Erfahrung nach verliert es einiges an Bequemlichkeit und Geschwindigkeit. Für von Menschen geschriebene Klassenerklärungen wird ein großes Problem das Leerzeichen sein. Verwenden Sie also egrep anstelle von grep. Auch LC_ALL = C für zusätzliche Geschwindigkeit. Der Einfachheit halber benutze ich oft:
LC_ALL=C egrep -irn "class[ ]*myclass([ ]|\n)" * | egrep "\.(inc|php[35]?)"
-i -- case insensitive
-r -- recursive for all file pattern (here *)
-n -- include the line number
LC_ALL=C -- search in ASCII, not in utf8, this is much faster.
[ ]* -- match any number of spaces before the class name
([ ]|\n) -- match a space or newline after the classname
Dies kann immer noch mit Kommentaren übereinstimmen, wie z. B. // class myclass exists in file
, aber ich finde, dass diese relativ klein sind und mit denen herausgefiltert werden können... | fgrep -v '//'
Sie können auch komplexere Dateimasken (z. B. um die meisten .inc- und .php-Dateien abzufangen) in das egrep-Dateimuster einfügen:
egrep "pattern" *.[ip]*
Das (mit den ersten Optionen) wird ziemlich schnell sein und meistens auf PHP-Dateien beschränkt sein.
HTH
Ich weiß, es heißt verwenden grep
, aber mein persönlicher Favorit ist zu verwenden ack-grep
:
ack-grep "class MyClass"
Dies wird rekursiv ausgeführt, listet den Dateinamen auf, in dem die Ergebnisse gefunden werden, mit den Zeilennummern, in denen sie gefunden werden, und hebt sie hervor. Um PHP-Dateien gezielt auszurichten, können Sie Folgendes ausführen:
ack-grep --type-set php:ext:php "path"
Das Paket bietet eine Vielzahl von Optionen. Ich würde es auf jeden Fall empfehlen (und die dazugehörige Manpage durchsuchen), um ausgefallene Dinge zu tun.
grep -r
nicht gegeben hat.