Як шукати рядок у файлі PHP за допомогою `grep`?


11

Я шукаю декларацію класу на сайті з сотнями PHP-файлів. Як я можу це зробити у поточній папці та вкладених папках за допомогою grep ?

Я протестував cdпапку, а потім щось подібне

grep -r 'class MyClass' *.php

Коли це мігрує до суперпользователя, ви можете сказати щось про те, що хотіли, що grep -rне дало вам.

Я розгублений - ти просто не відповідав собі? які були результати цього рядка? ви намагаєтесь додатково оптимізувати його? Будь ласка, передбачте читати це питання як хтось інший, тому що це заплутано і незрозуміло.
meder omuraliev

@ інші коментарі: Його 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, а не робити це з грепом. Однак якщо ти хочеш, ти можеш зробити щось подібне

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

Звичайно, це передбачає, що у вас є лише один простір між ними, classі myClassце може бути неправдою. Легко змінити регулярний вираз, щоб шукати будь-яку кількість пробілів.


4

Якщо ви використовуєте -r, ви, ймовірно, хочете рекурсивно шукати лише поточний каталог :

grep -r 'class MyClass' .

Зверніть увагу на період наприкінці сказаного.

Що ви сказали, grepщо ви хочете, щоб він рекурсивно шукав кожен *.phpфайл чи каталог , але ви, ймовірно, не мали каталогів, які закінчились розширенням .php. Вищенаведене є найпростішим можливим способом пошуку, але також включає файли інших типів, що особливо проблематично, коли у вас є скрізь каталоги .svn. Якщо у вас не так багато інших типів файлів, вищезазначене, як правило, достатньо і працює добре.

У більшості втілень grep немає способу вказувати розширення файлів, які можна шукати, тому ви, як правило, використовуєте пошук у поєднанні з ним:

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

-inameповідомляє деякі версії grep, що ви хочете здійснити нечутливий до регістру пошук імені файлів, але багато варіантів пошуку GNU не підтримують його, тому ви можете використовувати -nameзамість цього.

Наведений -execвище варіант має побічний ефект викликати grep для кожного файлу, що досить дорого.

Ще інші версії grep підтримують a, +який повідомляє знайти, щоб додати аргументи разом, щоб зменшити кількість викликів виконуваного файлу:

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

Часто рекомендований спосіб зменшити виклики - це використовувати xargs, які дозволять знімати grep якомога менше разів, але стільки разів, скільки потрібно:

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

xargsдостатньо розумний, щоб передавати греп до максимальної кількості аргументів, що підтримуються в командному рядку, але наведена вище версія не дуже добре обробляє певні символи, як пробіли. Наприклад, якщо "file.php" ім'я файлу grep отримало "аргумент" і аргумент "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

знайти. -тип f -name '* .php' -print0 | xargs -0 grep 'клас MyClass'


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

l відображається лише ім'я файлу

r відновлює

. пошук у поточній папці

--включати розширення лімітів файлів


1

Ймовірно, ви хочете нечутливості до регістру та толерантності пробілів, і grep припиняється, якщо в поточному каталозі не знайде жодних примірників потрібного шаблону файлів. Потрібно знати, з чого починати, і жоден збіг файлів не створює початкового шляху.

Якщо є хоча б один файл потрібного розширення, то ви можете використовувати egrep -ir. findі xargsпокажіть їх потужність за допомогою одиночних плоских (але дуже великих) каталогів, які не підключаються, а додаткові класифікатори (наприклад, якщо ви хочете шукати лише файли .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.

HTH


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.