¿Cómo busco una cadena en un archivo PHP usando `grep`?

11

Estoy buscando una declaración de clase en un sitio con cientos de archivos PHP. ¿Cómo puedo hacer esto en la carpeta y subcarpetas actuales usando grep ?

Probé cding a la carpeta y luego algo parecido

grep -r 'class MyClass' *.php
Peter Mortensen
fuente
Cuando esto migra a superusuario, es posible que desee decir algo sobre lo que quería que grep -rno le dio.
Estoy confundido, ¿no te respondiste? ¿Cuáles fueron los resultados de esa línea? ¿Estás tratando de optimizarlo aún más? imagina leer esta pregunta como alguien más, porque es confusa y poco clara.
meder omuraliev
@otros comentarios: Su declaración grep -r no está dando lo que quiere, a menos que todas las carpetas terminen con .php, lo cual probablemente no sea el caso ...
David Oneill
No obtuve nada en absoluto. Supongo que no funcionó porque sé que lo encuentra cuando estoy en la carpeta que tiene el archivo con esta clase
Encontré el archivo por suerte. Cuando busca el archivo en la carpeta que tiene el archivo PHP con esa línea, lo encuentra (no necesita -r). Si hago un CD en la raíz y hago la búsqueda con recursión -r, no devuelve nada.

Respuestas:

24

Puedes probar

grep -r --include=*.php "search string" /path/to/dir
rahul286
fuente
1
Funciona genial. Siempre me olvido, pero afortunadamente siempre hay una respuesta para ayudarme. :)
GolezTrol
@GolezTrol Me alegra saber que :-)
rahul286
9

Recomiendo que uses algo como ctags en lugar de hacerlo con grep. Sin embargo, si quieres, puedes hacer algo como

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

Por supuesto, esto supone que tiene un solo espacio entre classy myClassque podría no ser cierto. Sin embargo, es fácil cambiar la expresión regular para buscar cualquier cantidad de espacios en blanco.

Noufal Ibrahim
fuente
4

Si usa -r, probablemente desee buscar recursivamente solo el directorio actual :

grep -r 'class MyClass' .

Tenga en cuenta el período al final de lo anterior.

Lo que dijo grepfue que quería que buscara recursivamente cada *.phparchivo o directorio , pero que probablemente no tenía ningún directorio que terminara en una extensión .php. Lo anterior es la forma más simple posible de hacer la búsqueda, pero también incluye archivos de otros tipos, lo cual es especialmente problemático cuando tiene directorios .svn en todas partes. Si no tiene muchos otros tipos de archivos, lo anterior es generalmente suficiente y funciona bien.

La mayoría de las encarnaciones de grep no tienen una forma de especificar las extensiones de archivo que se pueden buscar, por lo que generalmente usa find junto con él:

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

-inamele dice a algunas versiones de grep que desea hacer una búsqueda de nombre de archivo que no distingue entre mayúsculas y minúsculas, pero muchas de las variantes de find que no son GNU no lo admiten, por lo que podría usarlo -nameen su lugar.

La -execopción anterior tiene el efecto secundario de invocar grep para cada archivo, lo cual es bastante costoso.

Aún otras versiones de grep soportan a +que le dice a find que agregue los argumentos juntos para reducir el número de invocaciones del ejecutable:

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

Una forma frecuentemente recomendada de reducir las invocaciones es usar xargs que dispararán grep tan pocas como sea posible, pero tantas veces como sea necesario:

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

xargses lo suficientemente inteligente como para pasar grep hasta el número máximo de argumentos admitidos en la línea de comando, pero la variación anterior no maneja muy bien ciertos caracteres como espacios. Por ejemplo, si 'el archivo.php' un nombre de archivo grep recibiría 'el' como argumento y 'archivo.php' como argumento para que no se encuentren ambos. En su lugar usamos:

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

print0y -0trabajen juntos y usen argumentos seguidos de un carácter nulo para que el argumento se identifique completa e inequívocamente.

Si alguna vez tiene más de un espacio después class, o una pestaña, es posible que desee permitir más caracteres cambiando la expresión regular:class[ \t]*MyClass

Esta publicación en StackOverflow tiene otros ejemplos y muestra cómo excluir ciertos directorios, como los directorios .svn.

Kaleb Pederson
fuente
Esto busca todos los archivos. También archivos que no son archivos .php.
GolezTrol
He actualizado la publicación para incluir muchos otros ejemplos.
Kaleb Pederson
3

Usando el ack siempre maravilloso ,

ack --php 'class MyClass'
efímero
fuente
1
grep -r 'class MyClass' *.php

buscará en todas las carpetas con nombres que terminen en .php

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

buscará la clase MyClass en todos los archivos en todas las subcarpetas, luego solo devolverá los que tengan .php en ellos.

David Oneill
fuente
1

find . -type f -name *.php -print -exec grep \"class MyClass\" {} \; le dará el contenido de la línea en la que se encuentra, así como la ruta al archivo.

prodigitalson
fuente
1

En caso de que los archivos coincidentes puedan tener nombres arbitrarios, debería considerar usar -print0

encontrar . -type f -name '* .php' -print0 | xargs -0 grep 'clase MyClass'

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

l solo muestra el nombre del archivo

r es recurrente

. busca en la carpeta actual

--incluir límites de extensión de nombre de archivo

Lleno
fuente
1

Probablemente desee insensibilidad a mayúsculas y tolerancia de espacios en blanco, y grep terminará si no encuentra ninguna instancia del patrón de archivo deseado en el directorio actual. Necesita saber por dónde empezar, por así decirlo, y ningún archivo coincidente no produce una ruta de inicio.

Si hay al menos un archivo de la extensión deseada, puede usar egrep -ir. findy xargsmuestra su poder con directorios planos (pero muy grandes) en los que grep falla y calificadores adicionales (por ejemplo, si desea buscar solo archivos .inc, .php y php3). Pero pierde bastante comodidad y velocidad en mi experiencia. Para las declaraciones de clases escritas en humanos, un gran problema será el espacio en blanco. Así que usa egrep en lugar de grep. También LC_ALL = C para velocidad extra. Por conveniencia, a menudo uso:

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

Esto todavía puede coincidir con los comentarios, como // class myclass exists in file, pero creo que son pequeños relativamente, y se pueden filtrar con... | fgrep -v '//'

También puede incluir máscaras de archivos más complejas (por ejemplo, para capturar la mayoría de los archivos .inc y .php) en el patrón de archivo egrep de la siguiente manera:

egrep "pattern" *.[ip]*

Eso (con las primeras opciones) será bastante rápido y se limitará principalmente a los archivos php.

HTH

Beracah
fuente
0

Sé que dice usar grep, pero mi favorito personal es usar ack-grep:

ack-grep "class MyClass"

Esto se ejecuta de forma recursiva, enumera el nombre del archivo en el que encuentra resultados, con números de línea para el lugar donde se encuentran, y resalta. Para apuntar específicamente a archivos php que puede ejecutar:

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

El paquete tiene una gran cantidad de opciones; Definitivamente lo recomendaría (y navegar por su página man asociada) para hacer cosas elegantes.

jhaagsma
fuente