Я шукаю декларацію класу на сайті з сотнями PHP-файлів. Як я можу це зробити у поточній папці та вкладених папках за допомогою grep ?
Я протестував cdпапку, а потім щось подібне
grep -r 'class MyClass' *.php
Я шукаю декларацію класу на сайті з сотнями PHP-файлів. Як я можу це зробити у поточній папці та вкладених папках за допомогою grep ?
Я протестував cdпапку, а потім щось подібне
grep -r 'class MyClass' *.php
Відповіді:
Я рекомендую вам використовувати щось на зразок ctags, а не робити це з грепом. Однак якщо ти хочеш, ти можеш зробити щось подібне
find <top level dir> -name \*.php | xargs grep "class MyClass"
Звичайно, це передбачає, що у вас є лише один простір між ними, classі myClassце може бути неправдою. Легко змінити регулярний вираз, щоб шукати будь-яку кількість пробілів.
Якщо ви використовуєте -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 каталоги.
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покажіть їх потужність за допомогою одиночних плоских (але дуже великих) каталогів, які не підключаються, а додаткові класифікатори (наприклад, якщо ви хочете шукати лише файли .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
Я знаю, що це говорить, використовуючи grep, але мій особистий фаворит - це використовувати ack-grep:
ack-grep "class MyClass"
Це запускається рекурсивно, перераховує ім'я файлу, в якому він знаходить результати, з номерами рядків, де вони знаходять, та виділяє. Щоб спеціально націлити файли php, можна запустити:
ack-grep --type-set php:ext:php "path"
У пакеті є безліч варіантів; Я б точно рекомендував його (і переглядав пов’язану з ним сторінку чоловіка) для виконання фантазійних речей.
grep -rне дало вам.