Come posso cercare una stringa in un file PHP usando `grep`?


11

Sto cercando una dichiarazione di classe su un sito con centinaia di file PHP. Come posso farlo nella cartella e nelle sottocartelle correnti usando grep ?

Ho provato cdla cartella e quindi qualcosa di simile

grep -r 'class MyClass' *.php

Quando questo passa a superutente, potresti voler dire qualcosa su ciò che volevi che grep -rnon ti ha dato.

Sono confuso - non hai appena risposto a te stesso? quali sono stati i risultati di quella linea? stai cercando di ottimizzarlo ulteriormente? immagina di leggere questa domanda come qualcun altro, perché è confusa e poco chiara.
meder omuraliev,

@altri commenti: la sua dichiarazione grep -r non sta dando ciò che vuole, a meno che tutte le cartelle non finiscano con .php che probabilmente non è il caso ...
David Oneill

Non ho ricevuto niente. Suppongo che non ha funzionato perché so che lo trova quando sono nella cartella che ha il file con questa classe

Ho trovato il file per fortuna. Quando cerca il file nella cartella che ha il file PHP con quella linea, lo trova (non c'è bisogno di -r). Se eseguo il CD alla radice e faccio la ricerca con ricorsione -r non restituisce nulla.

Risposte:


24

Puoi provare

grep -r --include=*.php "search string" /path/to/dir

1
Funziona alla grande. Continuo a dimenticare, ma per fortuna c'è sempre di nuovo questa risposta per aiutarmi. :)
GolezTrol,

@GolezTrol Sono contento di sapere che :-)
rahul286,

9

Ti consiglierei di usare qualcosa come i tag piuttosto che farlo con un grep. Tuttavia, se vuoi, puoi fare qualcosa del genere

 find <top level dir> -name \*.php | xargs grep "class MyClass"

Questo ovviamente presuppone che tu abbia un solo spazio tra classe myClassche potrebbe non essere vero. È facile cambiare la regexp per cercare un numero qualsiasi di spazi bianchi.


4

Se lo usi -r, probabilmente vorrai cercare ricorsivamente solo la directory corrente :

grep -r 'class MyClass' .

Nota il periodo alla fine di quanto sopra.

Quello che hai detto grepè che volevi che cercasse in modo ricorsivo ogni *.phpfile o directory , ma probabilmente non avevi alcuna directory che terminasse con un'estensione .php. Quanto sopra è il modo più semplice possibile per eseguire la ricerca, ma include anche file di altri tipi, il che è particolarmente problematico quando si hanno directory .svn ovunque. Se non hai molti altri tipi di file, quanto sopra è generalmente sufficiente e funziona bene.

La maggior parte delle incarnazioni di grep non ha un modo per specificare le estensioni dei file che possono essere ricercate, quindi generalmente si usa find insieme ad esso:

find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;

-inamedice ad alcune versioni di grep che si desidera effettuare una ricerca di nomi di file senza distinzione tra maiuscole e minuscole, ma molte delle varianti non GNU di find non lo supportano, quindi è possibile utilizzare -nameinvece.

L' -execopzione sopra ha l'effetto collaterale di invocare grep per ogni file, il che è abbastanza costoso.

Altre versioni di grep supportano a +che dice find di aggiungere gli argomenti insieme per ridurre il numero di invocazioni dell'eseguibile:

find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;

Un modo frequentemente raccomandato per ridurre le invocazioni è usare xargs che lanceranno grep il meno volte possibile ma quante volte necessario:

find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"

xargsè abbastanza intelligente da passare grep fino al numero massimo di argomenti supportati sulla riga di comando, ma la variazione sopra non gestisce molto bene alcuni caratteri come gli spazi. Ad esempio, se "file.php" un nome file grep ricevesse "the" come argomento e "file.php" come argomento, in modo che entrambi non vengano trovati. Invece usiamo:

find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"

print0e -0lavorare insieme e utilizzare argomenti seguiti da un carattere null in modo che l'argomento sia identificato in modo completo e inequivocabile.

Se hai mai più di uno spazio dopo class, o una scheda, potresti voler consentire più caratteri modificando la regex:class[ \t]*MyClass

Questo post su StackOverflow contiene altri esempi e mostra come escludere determinate directory, come le directory .svn.


Questo cerca tutti i file. Anche file che non sono file .php.
GolezTrol,

Ho aggiornato il post per includere molti altri esempi.
Kaleb Pederson,


1
grep -r 'class MyClass' *.php

cercherà in tutte le cartelle con nomi che finiscono con .php

grep -r 'class MyClass' . | grep .php

cercherà la classe MyClass in tutti i file in tutte le sottocartelle, quindi restituirà solo quelli che contengono .php.


1

find . -type f -name *.php -print -exec grep \"class MyClass\" {} \; ti fornirà il contenuto della riga su cui si trova e il percorso del file.


1

Nel caso in cui i file corrispondenti possano avere nomi arbitrari, dovresti prendere in considerazione l'utilizzo -print0

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


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

l mostra solo il nome del file

r è ricorsivo

. cerca nella cartella corrente

--include limita l'estensione del nome file


1

Probabilmente vuoi l'insensibilità al maiuscolo / minuscolo e la tolleranza agli spazi bianchi e grep terminerà se non trova alcuna istanza del modello di file desiderato nella directory corrente. Deve sapere da dove cominciare, per così dire, e nessun file abbinato non produce alcun percorso iniziale.

Se è presente almeno un file dell'estensione desiderata, è possibile utilizzare egrep -ir. finde xargsmostrano la loro potenza con singole directory flat (ma molto grandi) su cui grep fallisce e qualificatori extra (ad esempio se si desidera cercare solo file .inc, .php e php3). Ma nella mia esperienza perde un po 'di praticità e velocità. Per le dichiarazioni di classi scritte umane un grosso problema sarà lo spazio bianco. Quindi usa egrep invece di grep. Anche LC_ALL = C per una maggiore velocità. Per comodità, utilizzo spesso:

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

Questo può ancora abbinare i commenti, come // class myclass exists in file, ma trovo che siano relativamente piccoli e possono essere filtrati... | fgrep -v '//'

Puoi anche includere maschere di file più complesse (ad esempio, per catturare la maggior parte dei file .inc e .php) sul modello di file egrep in questo modo:

egrep "pattern" *.[ip]*

Quello (con le prime opzioni) sarà abbastanza veloce e per lo più limitato ai file php.

HTH


0

So che dice di usare grep, ma il mio preferito è usare ack-grep:

ack-grep "class MyClass"

Viene eseguito in modo ricorsivo, elenca il nome del file in cui trova i risultati, con i numeri di riga per la posizione in cui si trovano e mette in evidenza. Per indirizzare in modo specifico i file php è possibile eseguire:

ack-grep --type-set php:ext:php "path"

Il pacchetto ha molte opzioni; Lo consiglio vivamente (e navigando nella sua pagina man associata) per fare cose fantasiose.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.