Как мне найти строку в файле PHP, используя `grep`?


11

Я ищу объявление класса на сайте с сотнями PHP-файлов. Как я могу сделать это в текущей папке и подпапках, используя grep ?

Я проверил cdIN в папку, а затем что-то вроде

grep -r 'class MyClass' *.php

Когда это переходит на суперпользователя, вы можете захотеть сказать что-то о том, что вы хотели, что grep -rне дало вам.

Я в замешательстве - ты сам не ответил? каковы были результаты этой линии? Вы пытаетесь оптимизировать его? пожалуйста, представьте, что читаете этот вопрос как кто-то другой, потому что он запутанный и неясный.
медер омуралиев

@ другие комментарии: Его утверждение grep -r не дает того, что он хочет, если только все папки не заканчиваются на .php, что, вероятно, не так ...
David Oneill

Я ничего не получил вообще. Я предполагаю, что это не сработало, потому что я знаю, что находит его, когда я нахожусь в папке, где находится файл с этим классом

Я нашел файл по счастливой случайности. При поиске файла в папке, в которой находится PHP-файл с этой строкой, он находит его (нет необходимости в -r). Если я отправляю CD в корень и выполняю поиск с помощью рекурсии -r, он ничего не возвращает.

Ответы:


24

Можешь попробовать

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

1
Прекрасно работает. Я продолжаю забывать, но, к счастью, всегда есть этот ответ, чтобы помочь мне. :)
GolezTrol

@GolezTrol Рад знать, что :-)
rahul286

9

Я бы порекомендовал вам использовать что-то вроде ctags, а не с помощью grep. Однако, если вы хотите, вы можете сделать что-то вроде

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

Это, конечно, предполагает, что между вами есть только один пробел, classи myClassэто может быть неверно. Однако легко изменить регулярное выражение для поиска любого количества пробелов.


4

Если вы используете -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.


Это ищет все файлы. Также файлы, которые не являются .php файлами.
GolezTrol

Я обновил пост, чтобы включить много других примеров.
Калеб Педерсон


1
grep -r 'class MyClass' *.php

будет искать во всех папках с именами, заканчивающимися на .php

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

будет искать класс MyClass во всех файлах во всех подпапках, а затем будет возвращать только те, которые имеют .php в них.


1

find . -type f -name *.php -print -exec grep \"class MyClass\" {} \; даст вам содержимое строки, в которой он найден, а также путь к файлу.


1

В случае, если совпадающие файлы могут иметь произвольные имена, вы должны рассмотреть возможность использования -print0

находить . -type f -name '* .php' -print0 | xargs -0 grep 'class MyClass'


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

л показывает только имя файла

г

, поиск в текущей папке

--include ограничивает расширение файла


1

Возможно, вам нужна нечувствительность к регистру и допуск пробелов, и 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-файлами.

НТН


0

Я знаю, что это говорит об использовании grep, но мой личный фаворит - использовать ack-grep:

ack-grep "class MyClass"

Это выполняется рекурсивно, перечисляет имя файла, в котором он находит результаты, с номерами строк, где они находятся, и выделяет. Чтобы специально настроить php-файлы, вы можете запустить:

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

Пакет имеет множество вариантов; Я определенно рекомендую его (и просматриваю связанную с ним справочную страницу) для выполнения модных вещей.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.