Я ищу объявление класса на сайте с сотнями PHP-файлов. Как я могу сделать это в текущей папке и подпапках, используя grep ?
Я проверил cd
IN в папку, а затем что-то вроде
grep -r 'class MyClass' *.php
Я ищу объявление класса на сайте с сотнями PHP-файлов. Как я могу сделать это в текущей папке и подпапках, используя grep ?
Я проверил cd
IN в папку, а затем что-то вроде
grep -r 'class MyClass' *.php
Ответы:
Я бы порекомендовал вам использовать что-то вроде ctags, а не с помощью grep. Однако, если вы хотите, вы можете сделать что-то вроде
find <top level dir> -name \*.php | xargs grep "class MyClass"
Это, конечно, предполагает, что между вами есть только один пробел, class
и myClass
это может быть неверно. Однако легко изменить регулярное выражение для поиска любого количества пробелов.
Если вы используете -r
, вы, вероятно, хотите рекурсивно искать только текущий каталог :
grep -r 'class MyClass' .
Обратите внимание на период в конце выше.
Вы сказали, grep
что хотите, чтобы он выполнял рекурсивный поиск по каждому *.php
файлу или каталогу , но, скорее всего, у вас не было каталогов, заканчивающихся расширением .php. Выше приведен самый простой способ выполнить поиск, но он также включает файлы других типов, что особенно проблематично, когда у вас есть каталоги .svn везде. Если у вас нет много других типов файлов, вышеприведенного обычно достаточно и работает хорошо.
В большинстве воплощений grep нет способа указать расширения файлов, которые можно искать, поэтому вы обычно используете find вместе с ним:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;
-iname
сообщает некоторым версиям grep, что вы хотите выполнять поиск имени файла без учета регистра, но многие из вариантов поиска, не относящихся к GNU, не поддерживают его, поэтому вы можете использовать его -name
вместо этого.
-exec
Вариант выше , имеет побочный эффект вызова Grep для каждого файла, который является довольно дорогостоящим.
Тем не менее, другие версии grep поддерживают a, +
который сообщает find, чтобы добавлять аргументы вместе, чтобы уменьшить количество вызовов исполняемого файла:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;
Часто рекомендуемый способ уменьшить количество вызовов - использовать xargs, который будет запускать grep как можно меньше раз, но столько раз, сколько необходимо:
find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"
xargs
достаточно умен, чтобы передать grep до максимального числа аргументов, поддерживаемых в командной строке, но вышеописанный вариант не очень хорошо обрабатывает некоторые символы, например пробелы. Например, если в файле 'file.php' имя файла grep получит в качестве аргумента 'the', а в качестве аргумента 'file.php', оба файла не будут найдены. Вместо этого мы используем:
find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"
print0
и -0
работать вместе и использовать аргументы, за которыми следует нулевой символ, чтобы аргумент был полностью и однозначно идентифицирован.
Если у вас когда-либо будет больше одного пробела class
или табуляции, вы можете захотеть добавить больше символов, изменив регулярное выражение:class[ \t]*MyClass
Этот пост в StackOverflow содержит другие примеры и демонстрирует, как исключить определенные каталоги, например, каталоги .svn.
Используя когда-либо чудесное подтверждение ,
ack --php 'class MyClass'
grep -r 'class MyClass' *.php
будет искать во всех папках с именами, заканчивающимися на .php
grep -r 'class MyClass' . | grep .php
будет искать класс MyClass во всех файлах во всех подпапках, а затем будет возвращать только те, которые имеют .php в них.
find . -type f -name *.php -print -exec grep \"class MyClass\" {} \;
даст вам содержимое строки, в которой он найден, а также путь к файлу.
Возможно, вам нужна нечувствительность к регистру и допуск пробелов, и grep прекратит работу, если не найдет ни одного экземпляра желаемого шаблона файла в текущем каталоге. Он должен знать, с чего начать, и никакие файлы не дают начального пути.
Если существует хотя бы один файл с желаемым расширением, вы можете использовать egrep -ir. find
и xargs
продемонстрируйте их мощь с помощью единственных плоских (но очень больших) каталогов, в которых сбой grep, и дополнительных квалификаторов (например, если вы хотите искать только файлы .inc, .php и php3). Но это теряет немного удобства и скорости в моем опыте. Для объявлений, написанных человеком, большой проблемой будет пробел. Так что используйте egrep вместо grep. Также LC_ALL = C для дополнительной скорости. Для удобства я часто использую:
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
Это может соответствовать комментариям, таким как // class myclass exists in file
, но я считаю, что они относительно небольшие, и их можно отфильтровать с помощью... | fgrep -v '//'
Вы также можете включить более сложные маски файлов (например, чтобы перехватить большинство файлов .inc и .php) в шаблон файла egrep следующим образом:
egrep "pattern" *.[ip]*
Это (с первыми опциями) будет довольно быстрым и в основном ограничивается php-файлами.
НТН
Я знаю, что это говорит об использовании grep
, но мой личный фаворит - использовать ack-grep
:
ack-grep "class MyClass"
Это выполняется рекурсивно, перечисляет имя файла, в котором он находит результаты, с номерами строк, где они находятся, и выделяет. Чтобы специально настроить php-файлы, вы можете запустить:
ack-grep --type-set php:ext:php "path"
Пакет имеет множество вариантов; Я определенно рекомендую его (и просматриваю связанную с ним справочную страницу) для выполнения модных вещей.
grep -r
не дало вам.