Wie suche ich mit `grep` nach einer Zeichenfolge in einer PHP-Datei?

11

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 cdhabe den Ordner getestet und dann so etwas

grep -r 'class MyClass' *.php
Peter Mortensen
quelle
Wenn dies zu Superuser migriert wird, möchten Sie möglicherweise etwas über das sagen, was Sie wollten, was Ihnen grep -rnicht gegeben hat.
Ich bin verwirrt - hast du dir nicht einfach selbst geantwortet? Was waren die Ergebnisse dieser Linie? Versuchen Sie es weiter zu optimieren? Bitte stellen Sie sich vor, diese Frage als jemand anderes zu lesen, da sie verwirrend und unklar ist.
Meder Omuraliev
@ andere Kommentare: Seine grep -r Aussage gibt nicht, was er will, es sei denn, alle Ordner enden mit .php, was wahrscheinlich nicht der Fall ist ...
David Oneill
Ich habe überhaupt nichts bekommen. Ich nehme an, es hat nicht funktioniert, weil ich weiß, dass es es findet, wenn ich in dem Ordner bin, in dem sich die Datei mit dieser Klasse befindet
Ich habe die Datei durch Glück gefunden. Bei der Suche nach der Datei in dem Ordner, in dem sich die PHP-Datei mit dieser Zeile befindet, wird sie gefunden (keine Notwendigkeit für -r). Wenn ich eine CD in das Stammverzeichnis lege und die Suche mit Rekursion -r durchführe, wird nichts zurückgegeben.

Antworten:

24

Du kannst es versuchen

grep -r --include=*.php "search string" /path/to/dir
rahul286
quelle
1
Funktioniert super. Ich vergesse immer wieder, aber zum Glück gibt es immer wieder diese Antwort, um mir zu helfen. :)
GolezTrol
@GolezTrol Freut mich zu wissen, dass :-)
rahul286
9

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 classund myClassmöglicherweise nicht wahr haben. Es ist jedoch einfach, den regulären Ausdruck zu ändern, um nach einer beliebigen Anzahl von Leerzeichen zu suchen.

Noufal Ibrahim
quelle
4

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, grepwar, dass Sie wollten, dass jede *.phpDatei 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' {} \;

-inameteilt 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 -namestattdessen verwenden können.

Die -execobige 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"

xargsist 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"

print0und -0arbeiten 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 classoder 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.

Kaleb Pederson
quelle
Dies durchsucht alle Dateien. Auch Dateien, die keine .php-Dateien sind.
GolezTrol
Ich habe den Beitrag aktualisiert, um viele andere Beispiele aufzunehmen.
Kaleb Pederson
3

Mit dem immer wunderbaren ack ,

ack --php 'class MyClass'
kurzlebig
quelle
1
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.

David Oneill
quelle
1

find . -type f -name *.php -print -exec grep \"class MyClass\" {} \; Sie erhalten den Inhalt der Zeile sowie den Pfad zur Datei.

prodigitalson
quelle
1

Falls die übereinstimmenden Dateien möglicherweise beliebige Namen haben, sollten Sie die Verwendung in Betracht ziehen -print0

finden . -type f -name '* .php' -print0 | xargs -0 grep 'class MyClass'

wudeng
quelle
1
grep -rl 'class MyClass' . --include \*.php

l zeigt nur den Dateinamen

r ist rekursiv

. sucht im aktuellen Ordner

--include begrenzt die Dateinamenerweiterung

Voll
quelle
1

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. findund xargszeigen 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

Beracah
quelle
0

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.

jhaagsma
quelle